3
3
use crate :: errors:: * ;
4
4
use crate :: { Counter , Histogram } ;
5
5
use std:: borrow:: Borrow ;
6
+ use std:: borrow:: BorrowMut ;
7
+ use std:: marker:: PhantomData ;
6
8
use std:: ops:: { AddAssign , Deref , DerefMut } ;
7
9
use std:: sync:: { atomic, Arc , Mutex } ;
8
10
use std:: time;
@@ -88,15 +90,36 @@ struct Shared<C: Counter> {
88
90
phase : atomic:: AtomicUsize ,
89
91
}
90
92
93
+ /// See [`IdleRecorder`]. This guard borrows the idle [`Recorder`].
94
+ pub type IdleRecorderGuard < ' a , C > = IdleRecorder < & ' a mut Recorder < C > , C > ;
95
+
91
96
/// This guard denotes that a [`Recorder`] is currently idle, and should not be waited on by a
92
97
/// [`SyncHistogram`] phase-shift.
93
- pub struct IdleRecorderGuard < ' a , C : Counter > ( & ' a mut Recorder < C > ) ;
98
+ pub struct IdleRecorder < T , C : Counter >
99
+ where
100
+ T : BorrowMut < Recorder < C > > ,
101
+ {
102
+ recorder : Option < T > ,
103
+ c : PhantomData < C > ,
104
+ }
105
+
106
+ impl < T , C : Counter > IdleRecorder < T , C >
107
+ where
108
+ T : BorrowMut < Recorder < C > > ,
109
+ {
110
+ fn reactivate ( & mut self ) {
111
+ let recorder = if let Some ( ref mut r) = self . recorder {
112
+ r
113
+ } else {
114
+ // already reactivated
115
+ return ;
116
+ } ;
117
+
118
+ let recorder = recorder. borrow_mut ( ) ;
94
119
95
- impl < ' a , C : Counter > Drop for IdleRecorderGuard < ' a , C > {
96
- fn drop ( & mut self ) {
97
120
// the Recorder is no longer idle, so the reader has to wait for us again
98
121
// this basically means re-incrementing .recorders
99
- let mut crit = self . 0 . shared . truth . lock ( ) . unwrap ( ) ;
122
+ let mut crit = recorder . shared . truth . lock ( ) . unwrap ( ) ;
100
123
crit. recorders += 1 ;
101
124
102
125
// we need to figure out what phase we're joining
@@ -107,13 +130,35 @@ impl<'a, C: Counter> Drop for IdleRecorderGuard<'a, C> {
107
130
// to send), and bump the phase, all before we read it, which would lead us to believe that
108
131
// we were already synchronized when in reality we were not, which would stall the reader
109
132
// even if we issued more writes.
110
- self . 0 . last_phase = self . 0 . shared . phase . load ( atomic:: Ordering :: Acquire ) ;
133
+ recorder . last_phase = recorder . shared . phase . load ( atomic:: Ordering :: Acquire ) ;
111
134
112
135
// explicitly drop guard to ensure we don't accidentally drop it above
113
136
drop ( crit) ;
114
137
}
115
138
}
116
139
140
+ impl < C : Counter > IdleRecorder < Recorder < C > , C > {
141
+ /// Mark the wrapped [`Recorder`] as active again and return it.
142
+ pub fn activate ( mut self ) -> Recorder < C > {
143
+ self . reactivate ( ) ;
144
+ self . recorder . take ( ) . unwrap ( )
145
+ }
146
+
147
+ /// Clone the wrapped [`Recorder`].
148
+ pub fn recorder ( & self ) -> Recorder < C > {
149
+ self . recorder . as_ref ( ) . unwrap ( ) . clone ( )
150
+ }
151
+ }
152
+
153
+ impl < T , C : Counter > Drop for IdleRecorder < T , C >
154
+ where
155
+ T : BorrowMut < Recorder < C > > ,
156
+ {
157
+ fn drop ( & mut self ) {
158
+ self . reactivate ( )
159
+ }
160
+ }
161
+
117
162
impl < C : Counter > Recorder < C > {
118
163
fn with_hist < F , R > ( & mut self , f : F ) -> R
119
164
where
@@ -139,11 +184,7 @@ impl<C: Counter> Recorder<C> {
139
184
let _ = self . shared . sender . send ( h) . is_ok ( ) ; // if this is err, the reader went away
140
185
}
141
186
142
- /// Call this method if the Recorder will be idle for a while.
143
- ///
144
- /// Until the returned guard is dropped, the associated [`SyncHistogram`] will not wait for
145
- /// this recorder on a phase shift.
146
- pub fn idle ( & mut self ) -> IdleRecorderGuard < C > {
187
+ fn deactivate ( & mut self ) {
147
188
let phase;
148
189
{
149
190
// we're leaving rotation, so we need to decrement .recorders
@@ -160,8 +201,31 @@ impl<C: Counter> Recorder<C> {
160
201
}
161
202
}
162
203
self . last_phase = phase;
204
+ }
163
205
164
- IdleRecorderGuard ( self )
206
+ /// Call this method if the Recorder will be idle for a while.
207
+ ///
208
+ /// Until the returned guard is dropped, the associated [`SyncHistogram`] will not wait for
209
+ /// this recorder on a phase shift.
210
+ pub fn idle ( & mut self ) -> IdleRecorderGuard < C > {
211
+ self . deactivate ( ) ;
212
+ IdleRecorder {
213
+ recorder : Some ( self ) ,
214
+ c : PhantomData ,
215
+ }
216
+ }
217
+
218
+ /// Mark this `Recorder` as inactive.
219
+ ///
220
+ /// Until the returned guard is consumed, either by calling [`IdleRecorder::activate`] or by
221
+ /// dropping it, the associated [`SyncHistogram`] will not wait for this recorder on a phase
222
+ /// shift.
223
+ pub fn into_idle ( mut self ) -> IdleRecorder < Self , C > {
224
+ self . deactivate ( ) ;
225
+ IdleRecorder {
226
+ recorder : Some ( self ) ,
227
+ c : PhantomData ,
228
+ }
165
229
}
166
230
167
231
/// See [`Histogram::add`].
0 commit comments