@@ -116,15 +116,15 @@ impl<T: Serialize> Metrics<T> {
116116 ///
117117 /// * `metrics_dest` - Buffer for JSON formatted metrics. Needs to implement `Write` and `Send`.
118118 pub fn init ( & self , metrics_dest : Box < dyn Write + Send > ) -> Result < ( ) , MetricsError > {
119- if self . is_initialized . load ( Ordering :: Relaxed ) {
119+ if self . is_initialized . load ( Ordering :: Acquire ) {
120120 return Err ( MetricsError :: AlreadyInitialized ) ;
121121 }
122122 {
123123 let mut g = extract_guard ( self . metrics_buf . lock ( ) ) ;
124124
125125 * g = Some ( metrics_dest) ;
126126 }
127- self . is_initialized . store ( true , Ordering :: Relaxed ) ;
127+ self . is_initialized . store ( true , Ordering :: Release ) ;
128128 Ok ( ( ) )
129129 }
130130
@@ -148,7 +148,7 @@ impl<T: Serialize> Metrics<T> {
148148 /// The alternative is to hold a Mutex over the entire function call, but this increases the
149149 /// known deadlock potential.
150150 pub fn write ( & self ) -> Result < bool , MetricsError > {
151- if self . is_initialized . load ( Ordering :: Relaxed ) {
151+ if self . is_initialized . load ( Ordering :: Acquire ) {
152152 match serde_json:: to_string ( & self . app_metrics ) {
153153 Ok ( msg) => {
154154 if let Some ( guard) = extract_guard ( self . metrics_buf . lock ( ) ) . as_mut ( ) {
@@ -251,48 +251,45 @@ pub struct SharedIncMetric(AtomicUsize, AtomicUsize);
251251pub struct SharedStoreMetric ( AtomicUsize ) ;
252252
253253impl IncMetric for SharedIncMetric {
254- // While the order specified for this operation is still Relaxed, the actual instruction will
255- // be an asm "LOCK; something" and thus atomic across multiple threads, simply because of the
256- // fetch_and_add (as opposed to "store(load() + 1)") implementation for atomics.
257- // TODO: would a stronger ordering make a difference here?
258254 fn add ( & self , value : usize ) {
259- self . 0 . fetch_add ( value, Ordering :: Relaxed ) ;
255+ self . 0 . fetch_add ( value, Ordering :: AcqRel ) ;
260256 }
261257
262258 fn count ( & self ) -> usize {
263- self . 0 . load ( Ordering :: Relaxed )
259+ self . 0 . load ( Ordering :: Acquire )
264260 }
265261}
266262
267263impl StoreMetric for SharedStoreMetric {
268264 fn fetch ( & self ) -> usize {
269- self . 0 . load ( Ordering :: Relaxed )
265+ self . 0 . load ( Ordering :: Acquire )
270266 }
271267
272268 fn store ( & self , value : usize ) {
273- self . 0 . store ( value, Ordering :: Relaxed ) ;
269+ self . 0 . store ( value, Ordering :: Release ) ;
274270 }
275271}
276272
277273impl Serialize for SharedIncMetric {
278274 /// Reset counters of each metrics. Here we suppose that Serialize's goal is to help with the
279275 /// flushing of metrics.
280276 /// !!! Any print of the metrics will also reset them. Use with caution !!!
277+ /// !!! This function is not thread safe !!!
281278 fn serialize < S : Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
282279 // There's no serializer.serialize_usize() for some reason :(
283- let snapshot = self . 0 . load ( Ordering :: Relaxed ) ;
284- let res = serializer. serialize_u64 ( snapshot as u64 - self . 1 . load ( Ordering :: Relaxed ) as u64 ) ;
280+ let snapshot = self . count ( ) ;
281+ let res = serializer. serialize_u64 ( snapshot as u64 - self . 1 . load ( Ordering :: Acquire ) as u64 ) ;
285282
286283 if res. is_ok ( ) {
287- self . 1 . store ( snapshot, Ordering :: Relaxed ) ;
284+ self . 1 . store ( snapshot, Ordering :: Release ) ;
288285 }
289286 res
290287 }
291288}
292289
293290impl Serialize for SharedStoreMetric {
294291 fn serialize < S : Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
295- serializer. serialize_u64 ( self . 0 . load ( Ordering :: Relaxed ) as u64 )
292+ serializer. serialize_u64 ( self . 0 . load ( Ordering :: Acquire ) as u64 )
296293 }
297294}
298295
0 commit comments