@@ -13,21 +13,22 @@ let inner = unsafe { self.ptr.as_ref() };
13
13
14
14
We can update the atomic reference count as follows:
15
15
``` rust,ignore
16
- let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed );
16
+ let old_rc = inner.rc.fetch_add(1, Ordering::??? );
17
17
```
18
18
19
- As described in [ the standard library's implementation of ` Arc ` cloning] [ 2 ] :
20
- > Using a relaxed ordering is alright here, as knowledge of the original
21
- > reference prevents other threads from erroneously deleting the object.
22
- >
23
- > As explained in the [ Boost documentation] [ 1 ] :
24
- > > Increasing the reference counter can always be done with
25
- > > memory_order_relaxed: New references to an object can only be formed from an
26
- > > existing reference, and passing an existing reference from one thread to
27
- > > another must already provide any required synchronization.
28
- >
29
- > [ 1 ] : https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
30
- [ 2 ] : https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/alloc/src/sync.rs#L1171-L1181
19
+ But what ordering should we use here? We don't really have any code that will
20
+ need atomic synchronization when cloning, as we do not modify the internal value
21
+ while cloning. Thus, we can use a Relaxed ordering here, which implies no
22
+ happens-before relationship but is atomic. When ` Drop ` ping the Arc, however,
23
+ we'll need to atomically synchronize when decrementing the reference count. This
24
+ is described more in [ the section on the ` Drop ` implementation for
25
+ ` Arc ` ] ( arc-drop.md ) For more information on atomic relationships and Relaxed
26
+ ordering, see [ the section on atomics] ( atomics.md ) .
27
+
28
+ Thus, the code becomes this:
29
+ ``` rust,ignore
30
+ let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
31
+ ```
31
32
32
33
We'll need to add another import to use ` Ordering ` :
33
34
``` rust,ignore
@@ -75,8 +76,9 @@ use std::sync::atomic::Ordering;
75
76
impl<T> Clone for Arc<T> {
76
77
fn clone(&self) -> Arc<T> {
77
78
let inner = unsafe { self.ptr.as_ref() };
78
- // Using a relaxed ordering is alright here as knowledge of the original
79
- // reference prevents other threads from wrongly deleting the object.
79
+ // Using a relaxed ordering is alright here as we don't need any atomic
80
+ // synchronization here as we're not modifying or accessing the inner
81
+ // data.
80
82
let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
81
83
82
84
if old_rc >= isize::MAX as usize {
0 commit comments