#[derive(Debug)]
struct Point {
pub x: u32,
pub y: u32,
}
fn main() {
let a = Point{x: 10, y: 12};
let b = a; // Move semantics
// println!("Name: {}, Age: {}", a.x, a.y); // can not use here
println!("Name: {}, Age: {}", b.x, b.y);
}
With Copy
and Clone
the value can be copied:
#[derive(Debug, Copy, Clone)]
struct Point {
pub x: u32,
pub y: u32,
}
fn main() {
let a = Point{x: 10, y: 12};
let b = a; // Copy semantics
println!("Name: {}, Age: {}", a.x, a.y); // allowed
println!("Name: {}, Age: {}", b.x, b.y);
}
Clone
has two methods clone
and clone_from
:
#[derive(Debug, Copy, Clone)]
struct Point {
pub x: u32,
pub y: u32,
}
fn main() {
let a = Point{x: 10, y: 12};
let mut b = Point{x: 0, y: 0};
b.clone_from(&a);
println!("Name: {}, Age: {}", a.x, a.y);
println!("Name: {}, Age: {}", b.x, b.y);
}
Most scalar types are Copy
, immutable references are, too, but String
is not:
fn test_copy<T: Copy>(_t:T) {}
fn main() {
let x: i64 = 12;
let y: String = "abc".to_string();
test_copy(x);
test_copy(y); // Compile error, since String is not Copy
}
These are often perceived to be difficult. You have to know 3 things:
- A type
T
isSend
, if it is safe to send objects of type T between threads. - A type
T
isSync
, if it is safe to share objects of type T between threads and use them concurrently. - A type
T
isSync
, if and only if&T
isSend
.
Contrary to other traits, Send
and Sync
are usually derived automatically
by the compiler from what it already knows. Most elementary types are both
Send
and Sync
, but most (smart) pointers are not. A struct is Send
(or Sync
resp.), if and only if all its components are Send
(or Sync
respectively.
We investigate our smart pointers:
#[derive(Debug)]
struct Person {
pub name: String,
pub age: u32,
}
fn test_copy<T: Copy>(_t: T) { }
fn test_clone<T: Clone>(_t: T) { }
fn test_send<T: Send>(_t: T) { }
fn test_sync<T: Sync>(_t: T) { }
fn main() {
{
let mut b = Box::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b);
}
{
let mut b = std::rc::Rc::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b);
test_send(b); // error: not send
test_sync(b); // error: not sync
}
{
let mut b = std::sync::Arc::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b);
test_send(b);
test_sync(b);
}
{
let b = std::sync::Mutex::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b);
let bb = b.lock().unwrap();
test_copy(bb); // error: not copy
test_clone(bb); // error: not clone
test_send(bb); // error: not send
test_sync(bb);
}
{
let b = std::sync::RwLock::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b);
{
let bb = b.write().unwrap();
test_copy(bb); // error: not copy
test_clone(bb); // error: not clone
test_send(bb); // error: not send
test_sync(bb);
}
let bbb = b.read().unwrap();
test_copy(bbb); // error: not copy
test_clone(bbb); // error: not clone
test_send(bbb); // error: not send
test_sync(bbb);
}
{
let b = std::cell::RefCell::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b); // error: not sync
}
{
let b = std::cell::Cell::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b); // error: not sync
}
}
Copy
: https://doc.rust-lang.org/std/marker/trait.Copy.htmlClone
: https://doc.rust-lang.org/std/clone/trait.Clone.html- Rustonomicon
Send
andSync
: https://doc.rust-lang.org/nomicon/send-and-sync.html Send
: https://doc.rust-lang.org/std/marker/trait.Send.htmlSync
: https://doc.rust-lang.org/std/marker/trait.Sync.html- Rust book: https://doc.rust-lang.org/book/ch16-03-shared-state.html
- Video: https://youtu.be/B4wjkQZCkt8
- Overview: https://gist.github.com/max-itzpapalotl/18f7675a60f6f9603250367bcb63992e