Open kuzminrobin opened 6 months ago
let v = Arc::new(Unsync);
let clone = v.clone();
thread::spawn(move || {
clone.reference()
});
v.reference() // races with clone.reference()
Therefore Arc<Unsync>
cannot be Send
to prevent the cloned arc from being sent to another thread.
Similarly, Arc<Unsend>
cannot be Sync
to prevent getting cloned in another thread:
let v = Arc::new(Unsend);
worker.run(|| { // this closure only sends `&v` to the worker thread
thread_local.set(v.clone());
});
drop(v);
worker.run(|| {
let arc = thread_local.get();
let unsend = arc.into_inner();
drop(unsend); // we have somehow sent Unsend into the worker thread
});
The principle is that Arc can be used both by reference (by cloning) and by moving (by obviously sending the Arc), but its underlying reference can also be used as reference (normal Deref) and owned (by into_inner
or otherwise becoming the owning reference after all other arcs are dropped).
@SOF3, thank you for your reply.
I assume that with Unsync
and Unsend
you mean values of types that are not Sync
and not Send
respectively.
I'm not sure what you mean with .reference()
(I fail to find any docs about that) and intuitively I assume that you mean a pseudocode that deals with references to an Arc
instance.
Having your reply I feel that I'm not mature enough in Rust to fully and clearly understand your explanation, such that I can explain the same to someone else. But the main point of this GitHub issue is not for me to understand, but to see the explanation in the book, the main words of this GitHub issue are: "Would be nice to see in the book the clarification or details about that".
Thanks.
.reference()
refers to any placeholder function with a &self
receiver.
10.1.2. Base Code / Send and Sync. Fragment:
It is unclear from the text of the book why the line about
Send
has the fragmentSync +
:and why the line about
Sync
has a fragment+ Send
:Would be nice to see in the book the clarification or details about that.
I also looked at (and it is still unclear)