Hmm, your example was more difficult than the standard one since you had to use two levels of closures.
Since both are given to other threads, there are lifetime issues involved (see this post of mine explaining why), so you need a runtime mechanism to guarantee that the referee only gets dropped when there are no (owning) references left, which is what Arc
does.
Whenever some x: T
is "mentioned" in a closure that uses it by shared reference (e.g., printing it, or in your example, .lock()
ing it), the closure will use by default &x: &T
whenever you "mention" it, which requires that the closure do not outlive the local frame of x
(Rust will raise an error when that can happen, such as with threads).
The solution, to avoid feeding &x: &T
to the closure, is to feed it "a magic reference that artificially keeps the (heap-allocated) referee alive" a Arc<T>
.
For that to happen, you need to use a move
closure to force take ownership of the captures (i.e., prevent having &_
in the captures). Note that up until this point the key is about using a move
closure, Arc
is not needed yet.
Where Arc<T>
shines is to solve the issue you had: after giving a variable to a move
closure, you cannot use it again (unless it is Copy
).
The solution, which Arc
was designed for, is to (cheaply) .clone()
it so that what the closure captures is a "clone" of your local.
- The cloning is guaranteed to be "cheap" since all that
Arc
-cloning does is incrementing a counter, which is the way to "artifically keep the (heap-allocated) referee alive".
Back to your example and the two levels of closures, since you did not use server_sender_arc
outside the first move
closure, you did not need to .clone()
it. But then, within that outer closure, you did need to use it multiple times (c.f. the loop
). Hence the cloning.
It shadows the local var for ergonomics, but only withing the scope of the loop
, so all is fine: it may have been more beginner friendly if the clone had been declared with a different name, and if I had used that name in the inner closure.
You could mark my previous answer as the solving one (symbol below any post).