weak_self/lib.rs
1use std::cell::UnsafeCell;
2use std::fmt;
3use std::sync::{Arc, Weak};
4
5///WeakSelf is simple way to have a Weak pointer inside a data structure pointing to itself.
6///
7///
8///## Use Case
9///
10///
11///Sometimes you want to create a ```struct``` with a pointer to itself or just some other recursive data structure.
12///
13///
14///```rust ignore
15/// struct Foo {
16/// me: &Foo
17/// }
18///
19/// impl Foo {
20/// pub fn new() -> Foo {
21/// let foo = Foo{
22/// me: ????
23/// };
24/// foo
25/// }
26/// }
27///
28///```
29///
30///This create helps you do that:
31///
32///```rust
33/// use weak_self::WeakSelf;
34/// use std::sync::{Arc, Weak};
35/// pub struct Foo {
36/// weak_self: WeakSelf<Foo>
37/// }
38///
39/// impl Foo {
40/// pub fn new() -> Arc<Foo> {
41/// let foo = Arc::new(Foo{
42/// weak_self: WeakSelf::new()
43/// });
44/// foo.weak_self.init(&foo);
45/// foo
46/// }
47///
48/// fn weak(&self) -> Weak<Self> {
49/// self.weak_self.get()
50/// }
51/// }
52///
53///```
54///
55///
56///
57///## Dependencies
58///
59///This package depends on std only
60///
61///## Usage
62///
63///To use WeakSelf, add this to your `Cargo.toml`:
64///
65///```toml
66///[dependencies]
67///weakself = "1.0.2"
68///```
69///
70///
71///## License
72///
73///Licensed under the terms of MIT license and the Apache License (Version 2.0).
74///
75///See [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE) for details.
76///
77pub struct WeakSelf<T: ?Sized> {
78 cell: UnsafeCell<Option<Weak<T>>>
79}
80
81impl<T: ?Sized> WeakSelf<T> {
82 /// Constructs a new empty WeakSelf<T>
83 pub fn new() -> WeakSelf<T> {
84 WeakSelf {
85 cell: UnsafeCell::new(None)
86 }
87 }
88
89
90 /// Initialize the WeakSelf<T> with an Arc.
91 ///
92 /// Note: content must point be the only existing Arc, otherwise this method will panic
93 pub fn init(&self, content: &Arc<T>) {
94 if Arc::strong_count(content) != 1 || Arc::weak_count(content) != 0 {
95 panic!("Exclusive access to Arc<T> is required while initializing WeakSelf<T>");
96 }
97 let weak = Arc::downgrade(content);
98 unsafe {
99 *self.cell.get() = Some(weak);
100 }
101 }
102
103 /// get Some Weak<T> pointer to the content, or None if not yet initialized
104 pub fn try_get(&self) -> Option<&Weak<T>> {
105 unsafe {
106 match *self.cell.get() {
107 Some(ref weak) => Some(&weak),
108 None => None
109 }
110 }
111 }
112
113 /// get a Weak<T> pointer to the content, or panic if not yet initialized
114 pub fn get(&self) -> Weak<T> {
115 self.try_get().expect("expected WeakSelf to be initialized").clone()
116 }
117}
118
119unsafe impl<T: ?Sized + Sync + Send> Sync for WeakSelf<T> {}
120
121unsafe impl<T: ?Sized + Sync + Send> Send for WeakSelf<T> {}
122
123
124impl<T: ?Sized + fmt::Debug> fmt::Debug for WeakSelf<T> {
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 match self.try_get() {
127 None => { write!(f, "Empty WeakSelf<T>") }
128 Some(weak) => fmt::Debug::fmt(weak, f),
129 }
130 }
131}
132
133
134impl<T: ?Sized> Default for WeakSelf<T> {
135 fn default() -> Self {
136 WeakSelf::new()
137 }
138}
139