record progress: smart pointers
This commit is contained in:
parent
8f317fa4dd
commit
1119249fa1
4 changed files with 221 additions and 10 deletions
|
@ -1,6 +1,6 @@
|
||||||
DON'T EDIT THIS FILE!
|
DON'T EDIT THIS FILE!
|
||||||
|
|
||||||
box1
|
threads1
|
||||||
|
|
||||||
intro1
|
intro1
|
||||||
intro2
|
intro2
|
||||||
|
@ -76,4 +76,8 @@ iterators1
|
||||||
iterators2
|
iterators2
|
||||||
iterators3
|
iterators3
|
||||||
iterators4
|
iterators4
|
||||||
iterators5
|
iterators5
|
||||||
|
box1
|
||||||
|
rc1
|
||||||
|
arc1
|
||||||
|
cow1
|
|
@ -1,4 +1,45 @@
|
||||||
|
// In this exercise, we are given a `Vec` of `u32` called `numbers` with values
|
||||||
|
// ranging from 0 to 99. We would like to use this set of numbers within 8
|
||||||
|
// different threads simultaneously. Each thread is going to get the sum of
|
||||||
|
// every eighth value with an offset.
|
||||||
|
//
|
||||||
|
// The first thread (offset 0), will sum 0, 8, 16, …
|
||||||
|
// The second thread (offset 1), will sum 1, 9, 17, …
|
||||||
|
// The third thread (offset 2), will sum 2, 10, 18, …
|
||||||
|
// …
|
||||||
|
// The eighth thread (offset 7), will sum 7, 15, 23, …
|
||||||
|
//
|
||||||
|
// Each thread should own a reference-counting pointer to the vector of
|
||||||
|
// numbers. But `Rc` isn't thread-safe. Therefore, we need to use `Arc`.
|
||||||
|
//
|
||||||
|
// Don't get distracted by how threads are spawned and joined. We will practice
|
||||||
|
// that later in the exercises about threads.
|
||||||
|
|
||||||
|
// Don't change the lines below.
|
||||||
|
#![forbid(unused_imports)]
|
||||||
|
use std::{sync::Arc, thread};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// DON'T EDIT THIS SOLUTION FILE!
|
let numbers: Vec<_> = (0..100u32).collect();
|
||||||
// It will be automatically filled after you finish the exercise.
|
|
||||||
|
let shared_numbers = Arc::new(numbers);
|
||||||
|
// ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
let mut join_handles = Vec::new();
|
||||||
|
|
||||||
|
for offset in 0..8 {
|
||||||
|
let child_numbers = Arc::clone(&shared_numbers);
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
let handle = thread::spawn(move || {
|
||||||
|
let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum();
|
||||||
|
println!("Sum of offset {offset} is {sum}");
|
||||||
|
});
|
||||||
|
|
||||||
|
join_handles.push(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
for handle in join_handles.into_iter() {
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,69 @@
|
||||||
fn main() {
|
// This exercise explores the `Cow` (Clone-On-Write) smart pointer. It can
|
||||||
// DON'T EDIT THIS SOLUTION FILE!
|
// enclose and provide immutable access to borrowed data and clone the data
|
||||||
// It will be automatically filled after you finish the exercise.
|
// lazily when mutation or ownership is required. The type is designed to work
|
||||||
|
// with general borrowed data via the `Borrow` trait.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
fn abs_all(input: &mut Cow<[i32]>) {
|
||||||
|
for ind in 0..input.len() {
|
||||||
|
let value = input[ind];
|
||||||
|
if value < 0 {
|
||||||
|
// Clones into a vector if not already owned.
|
||||||
|
input.to_mut()[ind] = -value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reference_mutation() {
|
||||||
|
// Clone occurs because `input` needs to be mutated.
|
||||||
|
let vec = vec![-1, 0, 1];
|
||||||
|
let mut input = Cow::from(&vec);
|
||||||
|
abs_all(&mut input);
|
||||||
|
assert!(matches!(input, Cow::Owned(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reference_no_mutation() {
|
||||||
|
// No clone occurs because `input` doesn't need to be mutated.
|
||||||
|
let vec = vec![0, 1, 2];
|
||||||
|
let mut input = Cow::from(&vec);
|
||||||
|
abs_all(&mut input);
|
||||||
|
assert!(matches!(input, Cow::Borrowed(_)));
|
||||||
|
// ^^^^^^^^^^^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn owned_no_mutation() {
|
||||||
|
// We can also pass `vec` without `&` so `Cow` owns it directly. In this
|
||||||
|
// case, no mutation occurs (all numbers are already absolute) and thus
|
||||||
|
// also no clone. But the result is still owned because it was never
|
||||||
|
// borrowed or mutated.
|
||||||
|
let vec = vec![0, 1, 2];
|
||||||
|
let mut input = Cow::from(vec);
|
||||||
|
abs_all(&mut input);
|
||||||
|
assert!(matches!(input, Cow::Owned(_)));
|
||||||
|
// ^^^^^^^^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn owned_mutation() {
|
||||||
|
// Of course this is also the case if a mutation does occur (not all
|
||||||
|
// numbers are absolute). In this case, the call to `to_mut()` in the
|
||||||
|
// `abs_all` function returns a reference to the same data as before.
|
||||||
|
let vec = vec![-1, 0, 1];
|
||||||
|
let mut input = Cow::from(vec);
|
||||||
|
abs_all(&mut input);
|
||||||
|
assert!(matches!(input, Cow::Owned(_)));
|
||||||
|
// ^^^^^^^^^^^^^
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,105 @@
|
||||||
fn main() {
|
// In this exercise, we want to express the concept of multiple owners via the
|
||||||
// DON'T EDIT THIS SOLUTION FILE!
|
// `Rc<T>` type. This is a model of our solar system - there is a `Sun` type and
|
||||||
// It will be automatically filled after you finish the exercise.
|
// multiple `Planet`s. The planets take ownership of the sun, indicating that
|
||||||
|
// they revolve around the sun.
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Sun;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Planet {
|
||||||
|
Mercury(Rc<Sun>),
|
||||||
|
Venus(Rc<Sun>),
|
||||||
|
Earth(Rc<Sun>),
|
||||||
|
Mars(Rc<Sun>),
|
||||||
|
Jupiter(Rc<Sun>),
|
||||||
|
Saturn(Rc<Sun>),
|
||||||
|
Uranus(Rc<Sun>),
|
||||||
|
Neptune(Rc<Sun>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Planet {
|
||||||
|
fn details(&self) {
|
||||||
|
println!("Hi from {self:?}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rc1() {
|
||||||
|
let sun = Rc::new(Sun);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference
|
||||||
|
|
||||||
|
let mercury = Planet::Mercury(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 2 references
|
||||||
|
mercury.details();
|
||||||
|
|
||||||
|
let venus = Planet::Venus(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 3 references
|
||||||
|
venus.details();
|
||||||
|
|
||||||
|
let earth = Planet::Earth(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 4 references
|
||||||
|
earth.details();
|
||||||
|
|
||||||
|
let mars = Planet::Mars(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 5 references
|
||||||
|
mars.details();
|
||||||
|
|
||||||
|
let jupiter = Planet::Jupiter(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 6 references
|
||||||
|
jupiter.details();
|
||||||
|
|
||||||
|
let saturn = Planet::Saturn(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 7 references
|
||||||
|
saturn.details();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
let uranus = Planet::Uranus(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 8 references
|
||||||
|
uranus.details();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
let neptune = Planet::Neptune(Rc::clone(&sun));
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 9 references
|
||||||
|
neptune.details();
|
||||||
|
|
||||||
|
assert_eq!(Rc::strong_count(&sun), 9);
|
||||||
|
|
||||||
|
drop(neptune);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 8 references
|
||||||
|
|
||||||
|
drop(uranus);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 7 references
|
||||||
|
|
||||||
|
drop(saturn);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 6 references
|
||||||
|
|
||||||
|
drop(jupiter);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 5 references
|
||||||
|
|
||||||
|
drop(mars);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 4 references
|
||||||
|
|
||||||
|
drop(earth);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 3 references
|
||||||
|
|
||||||
|
drop(venus);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 2 references
|
||||||
|
|
||||||
|
drop(mercury);
|
||||||
|
println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference
|
||||||
|
|
||||||
|
assert_eq!(Rc::strong_count(&sun), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue