1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
use crate::cell::cell::ShareCell;
use crate::Core;
use std::rc::{Rc, Weak};

/// Ref-counted shared mutable data
///
/// This allows synchronous modification of shared state from actor
/// methods.  Note that if you only wish to share immutable data
/// between actors, it's less verbose to simply use `Rc` from the
/// standard library.  Also you might wish to handle very small
/// amounts of shared mutable data with `Rc<Cell>` instead.
///
/// [`Share`] is provided as a compile-time-checked zero-cost
/// alternative to `Rc<RefCell>`.  If [`Share`] didn't exist, the
/// temptation to use `Rc<RefCell>` occasionally would likely be too
/// great.  However `Rc<RefCell>` brings the risk of unexpected
/// runtime panics.  Modification of one piece of code might
/// unexpectedly cause another distant piece of code to crash, but
/// quite possibly only under certain conditions which makes that
/// failure hard to anticipate in testing.  In short `Rc<RefCell>`
/// should be avoided wherever possible.  With [`Share`] everything is
/// checked at compile time.
///
/// Note that using [`Share`], `Rc<RefCell>` or `Rc<Cell>` breaks the
/// actor model.  Using them to share mutable data between actors
/// effectively causes those actors to be bound together in a group.
/// It would be impossible to split one of those actors off to another
/// process or over a remote link.  However the actor model still
/// applies to the group's external interface.
///
/// So this must be used with some knowledge of the trade-offs.  It
/// could easily lead to dependency on the order of execution of
/// actors.  Treat this as similar in danger level to shared memory
/// between threads or IPC shared memory between processes.  You don't
/// need locking however because if you get a mutable reference to the
/// contents you'll have exclusive access until you give it up thanks
/// to Rust's borrow checker.
///
/// To borrow more than one [`Share`] instance at a time, see
/// [`Core::share_rw2`] and [`Core::share_rw3`].
///
/// It's not possible to pass a [`Core`] reference to methods on a
/// [`Share`] item due to borrowing restrictions.  If you need a
/// [`Core`] reference, then use arguments of "`this: &Share<Self>,
/// core: &mut Core`" instead of "`&mut self`", and do `self` access
/// via `this.rw(core)`.  (However if it's getting this complicated,
/// maybe consider whether the shared data should be made into an
/// actor instead, or whether some other approach would be better.)
///
/// By default borrow-checking of access to the contents of the
/// [`Share`] is handled at compile-time using a `TCell` or `TLCell`
/// with its owner in [`Core`], so it is zero-cost and compiles down
/// to a direct pointer access to the contents of a `struct`, just as
/// if the [`Share`] wasn't there.  However cloning a [`Share`] has
/// the normal `Rc` overheads.
///
/// [`Core::share_rw2`]: struct.Core.html#method.share_rw2
/// [`Core::share_rw3`]: struct.Core.html#method.share_rw3
/// [`Core`]: struct.Core.html
/// [`Share`]: struct.Share.html
pub struct Share<T> {
    pub(crate) rc: Rc<ShareCell<T>>,
}

impl<T> Share<T> {
    /// Create a new Share instance
    pub fn new(core: &Core, val: T) -> Self {
        Self {
            rc: Rc::new(core.sharecell_owner.cell(val)),
        }
    }

    /// Get a read-only (immutable, shared) reference to the contents
    /// of the [`Share`] instance.  By default this is a static check,
    /// which compiles down to a direct access.
    ///
    /// [`Share`]: struct.Share.html
    #[inline]
    pub fn ro<'a>(&'a self, core: &'a Core) -> &'a T {
        core.sharecell_owner.ro(&self.rc)
    }

    /// Get a read-write (mutable, exclusive) reference to the
    /// contents of the [`Share`] instance.  By default this is a
    /// static check, which compiles down to a direct access.
    ///
    /// To access more than one [`Share`] instance at the same time,
    /// see [`Core::share_rw2`] and [`Core::share_rw3`].
    ///
    /// [`Core::share_rw2`]: struct.Core.html#method.share_rw2
    /// [`Core::share_rw3`]: struct.Core.html#method.share_rw3
    /// [`Share`]: struct.Share.html
    #[inline]
    pub fn rw<'a>(&'a self, core: &'a mut Core) -> &'a mut T {
        core.sharecell_owner.rw(&self.rc)
    }

    /// Create a [`ShareWeak`] reference to the contained object
    ///
    /// [`ShareWeak`]: struct.ShareWeak.html
    #[inline]
    pub fn downgrade(&self) -> ShareWeak<T> {
        ShareWeak {
            weak: Rc::downgrade(&self.rc),
        }
    }

    /// Return the number of strong references to the shared data
    #[inline]
    pub fn strong_count(&self) -> usize {
        Rc::strong_count(&self.rc)
    }

    /// Return the number of weak references to the shared data
    #[inline]
    pub fn weak_count(&self) -> usize {
        Rc::weak_count(&self.rc)
    }
}

impl<T> Clone for Share<T> {
    /// Return another reference to the shared data
    fn clone(&self) -> Self {
        Self {
            rc: self.rc.clone(),
        }
    }
}

/// Weak reference to a [`Share`]
///
/// This reference does not stop the [`Share`] from being dropped, but
/// can be used to recover a [`Share`] reference if it is still alive
/// due to a strong reference held elsewhere.
///
/// [`Share`]: struct.Share.html
pub struct ShareWeak<T> {
    weak: Weak<ShareCell<T>>,
}

impl<T> ShareWeak<T> {
    /// If there are still strong references to the shared data,
    /// returns a new [`Share`].  Otherwise the shared data has been
    /// dropped, and so returns `None`.
    ///
    /// [`Share`]: struct.Share.html
    pub fn upgrade(&self) -> Option<Share<T>> {
        self.weak.upgrade().map(|rc| Share { rc })
    }

    /// Return the number of strong references to the shared data
    pub fn strong_count(&self) -> usize {
        self.weak.strong_count()
    }

    /// Return the number of weak references to the shared data,
    /// including this one, or 0 if there are no strong pointers
    /// remaining.
    pub fn weak_count(&self) -> usize {
        self.weak.weak_count()
    }
}

impl<T> Clone for ShareWeak<T> {
    /// Return another weak reference to the shared data
    fn clone(&self) -> Self {
        Self {
            weak: self.weak.clone(),
        }
    }
}