58
58
//! # };
59
59
//! ```
60
60
61
- use futures :: executor :: block_on ;
61
+ pub use async_std :: future :: { timeout , TimeoutError } ;
62
62
use std:: {
63
63
cmp:: Eq ,
64
64
collections:: HashMap ,
65
65
hash:: Hash ,
66
66
sync:: { Arc , RwLock } ,
67
67
} ;
68
68
69
+ pub struct SlockData < T > {
70
+ pub version : u32 ,
71
+ pub value : T ,
72
+ pub hook : Option < Box < dyn FnMut ( & T ) > > ,
73
+ }
74
+
69
75
pub struct Slock < T > {
70
- lock : Arc < RwLock < T > > ,
76
+ lock : Arc < RwLock < SlockData < T > > > ,
71
77
}
72
78
73
79
impl < T > Slock < T > {
74
80
/// Create a new Slock with a given initial value.
75
81
pub fn new ( value : T ) -> Self {
82
+ let data = SlockData {
83
+ version : 0 ,
84
+ value,
85
+ hook : None ,
86
+ } ;
76
87
Self {
77
- lock : Arc :: new ( RwLock :: new ( value ) ) ,
88
+ lock : Arc :: new ( RwLock :: new ( data ) ) ,
78
89
}
79
90
}
80
91
@@ -87,12 +98,17 @@ impl<T> Slock<T> {
87
98
/// let name = lock.map(|v| v.name).await;
88
99
/// # };
89
100
/// ```
90
- pub async fn map < F , U > ( & self , mapper : F ) -> U
101
+ pub async fn map < F , U > ( & self , mapper : F ) -> Result < U , TimeoutError >
91
102
where
92
103
F : FnOnce ( & T ) -> U ,
93
104
{
94
105
match self . lock . read ( ) {
95
- Ok ( v) => mapper ( & * v) ,
106
+ Ok ( v) => {
107
+ timeout ( std:: time:: Duration :: from_secs ( 1 ) , async {
108
+ mapper ( & v. value )
109
+ } )
110
+ . await
111
+ }
96
112
Err ( _) => panic ! ( "Slock could not read for map!" ) ,
97
113
}
98
114
}
@@ -111,12 +127,23 @@ impl<T> Slock<T> {
111
127
F : FnOnce ( T ) -> T ,
112
128
{
113
129
match self . lock . write ( ) {
114
- Ok ( mut v ) => {
115
- let ptr = & mut * v as * mut T ;
130
+ Ok ( mut data ) => {
131
+ let ptr = & mut data . value as * mut T ;
116
132
unsafe {
117
- let new = setter ( ptr. read ( ) ) ;
118
- ptr. write ( new) ;
133
+ let new = timeout ( std:: time:: Duration :: from_secs ( 1 ) , async {
134
+ setter ( ptr. read ( ) )
135
+ } )
136
+ . await ;
137
+ if let Ok ( new) = new {
138
+ timeout ( std:: time:: Duration :: from_secs ( 1 ) , async {
139
+ data. hook . as_mut ( ) . map ( |hook| hook ( & new) ) ;
140
+ } )
141
+ . await
142
+ . ok ( ) ;
143
+ ptr. write ( new) ;
144
+ }
119
145
}
146
+ data. version += 1 ;
120
147
}
121
148
Err ( _) => panic ! ( "Slock could not write!" ) ,
122
149
}
@@ -139,16 +166,28 @@ impl<T> Slock<T> {
139
166
/// Returns the lock's atomic reference counter.
140
167
/// This is unsafe as using it can no longer guarantee
141
168
/// deadlocks won't occur.
142
- pub unsafe fn get_raw_arc ( & self ) -> Arc < RwLock < T > > {
169
+ pub unsafe fn get_raw_arc ( & self ) -> Arc < RwLock < SlockData < T > > > {
143
170
self . lock . clone ( )
144
171
}
172
+
173
+ pub fn hook < F : ' static > ( & self , hook : F )
174
+ where
175
+ F : FnMut ( & T ) ,
176
+ {
177
+ match self . lock . write ( ) {
178
+ Ok ( mut data) => {
179
+ data. hook = Some ( Box :: new ( hook) ) ;
180
+ }
181
+ Err ( _) => panic ! ( "Slock could not write!" ) ,
182
+ }
183
+ }
145
184
}
146
185
147
186
impl < T : Clone > Slock < T > {
148
187
/// Returns a clone of the lock's data.
149
188
pub async fn get_clone ( & self ) -> T {
150
189
match self . lock . read ( ) {
151
- Ok ( v) => v. clone ( ) ,
190
+ Ok ( v) => v. value . clone ( ) ,
152
191
Err ( _) => panic ! ( "Slock could not read for clone!" ) ,
153
192
}
154
193
}
@@ -174,7 +213,7 @@ impl<T> Slock<Vec<T>> {
174
213
impl < T > Slock < Slock < T > > {
175
214
/// Converts from `Slock<Slock<T>>` to `Slock<T>`
176
215
pub async fn flatten ( & self ) -> Slock < T > {
177
- self . map ( |inner| inner. split ( ) ) . await
216
+ self . map ( |inner| inner. split ( ) ) . await . unwrap ( )
178
217
}
179
218
}
180
219
@@ -210,44 +249,21 @@ impl<K: Eq + Hash + Copy, V> SlockMap<K, V> {
210
249
hash_map. get ( & key) . map ( |inner| inner. split ( ) )
211
250
} )
212
251
. await
252
+ . unwrap ( )
213
253
}
214
254
}
215
255
216
- macro_rules! impl_op {
217
- ( $name: ident, $name_assign: ident, $fun: ident, $op: tt) => {
218
- impl <T > std:: ops:: $name_assign<T > for Slock <T >
219
- where
220
- T : Copy + std:: ops:: $name<T , Output = T >,
221
- T : From <T >,
222
- {
223
- fn $fun( & mut self , other: T ) {
224
- block_on( self . set( |v| v $op other) ) ;
225
- }
226
- }
227
- } ;
228
- }
229
-
230
- impl_op ! ( Add , AddAssign , add_assign, +) ;
231
- impl_op ! ( Sub , SubAssign , sub_assign, -) ;
232
- impl_op ! ( Mul , MulAssign , mul_assign, * ) ;
233
- impl_op ! ( Div , DivAssign , div_assign, /) ;
234
- impl_op ! ( Rem , RemAssign , rem_assign, %) ;
235
-
236
256
impl < T : Copy > Slock < T > {
237
257
/// If a lock's data implements copy, this will return an owned copy of it.
238
258
pub async fn get ( & self ) -> T {
239
259
match self . lock . read ( ) {
240
- Ok ( v) => * v ,
260
+ Ok ( v) => v . value ,
241
261
Err ( _) => panic ! ( "Slock could not read for clone!" ) ,
242
262
}
243
263
}
244
264
}
245
265
246
- impl < T : Clone > Clone for Slock < T > {
247
- /// Creates a clone of the lock and its data.
248
- /// This operation is blocking.
249
- /// Prefer `clone_async`
250
- fn clone ( & self ) -> Self {
251
- return Slock :: new ( block_on ( self . get_clone ( ) ) ) ;
252
- }
253
- }
266
+ pub mod blocking;
267
+
268
+ unsafe impl < T > Send for Slock < T > { }
269
+ unsafe impl < T > Sync for Slock < T > { }
0 commit comments