@@ -302,14 +302,13 @@ where
302302 /// Unlike [`publish`](Self::publish), this never spins or waits. Use it on latency-sensitive
303303 /// paths where skipping a publish is preferable to blocking; call again later or fall back to
304304 /// [`publish`](Self::publish) if you must ensure visibility.
305- ///
306305 /// Returns `true` if a publish occurred, `false` otherwise.
307-
308306 pub fn try_publish ( & mut self ) -> bool {
309307 let epochs = Arc :: clone ( & self . epochs ) ;
310308 let mut epochs = epochs. lock ( ) . unwrap ( ) ;
311309
312- // we're over-estimating here, but slab doesn't expose its max index
310+ // This wait loop is exactly like the one in wait, except that if we find a reader that
311+ // has not observed the latest swap, we return rather than spin-and-retry.
313312 self . last_epochs . resize ( epochs. capacity ( ) , 0 ) ;
314313 for ( ri, epoch) in epochs. iter ( ) {
315314 if self . last_epochs [ ri] % 2 == 0 {
@@ -326,8 +325,13 @@ where
326325 return false ;
327326 }
328327 }
329- self . do_publish ( & mut epochs) ;
330- return true ;
328+ #[ cfg( test) ]
329+ {
330+ self . is_waiting . store ( false , Ordering :: Relaxed ) ;
331+ }
332+ self . update_and_swap ( & mut epochs) ;
333+
334+ true
331335 }
332336
333337 /// Publish all operations append to the log to reads.
@@ -349,11 +353,13 @@ where
349353
350354 self . wait ( & mut epochs) ;
351355
352- self . do_publish ( & mut epochs)
356+ self . update_and_swap ( & mut epochs)
353357 }
354358
355- /// Actual doing the publishing
356- fn do_publish (
359+ /// Brings `w_handle` up to date with the oplog, then swaps `r_handle` and `w_handle`.
360+ ///
361+ /// This method must only be called when all readers have exited `w_handle` (e.g., after `wait`)
362+ fn update_and_swap (
357363 & mut self ,
358364 epochs : & mut MutexGuard < ' _ , slab:: Slab < Arc < AtomicUsize > > > ,
359365 ) -> & mut Self {
@@ -766,7 +772,7 @@ mod tests {
766772 // Case 1: A reader has not advanced (odd and unchanged) -> returns false
767773 let mut epochs_slab = Slab :: new ( ) ;
768774 let idx = epochs_slab. insert ( Arc :: new ( AtomicUsize :: new ( 1 ) ) ) ; // odd epoch, "in read"
769- // Ensure last_epochs sees this reader as odd and unchanged
775+ // Ensure last_epochs sees this reader as odd and unchanged
770776 w. last_epochs = vec ! [ 0 ; epochs_slab. capacity( ) ] ;
771777 w. last_epochs [ idx] = 1 ;
772778 w. epochs = Arc :: new ( Mutex :: new ( epochs_slab) ) ;
0 commit comments