@@ -302,14 +302,14 @@ 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- ///
305+ ///
306306 /// Returns `true` if a publish occurred, `false` otherwise.
307-
308307 pub fn try_publish ( & mut self ) -> bool {
309308 let epochs = Arc :: clone ( & self . epochs ) ;
310309 let mut epochs = epochs. lock ( ) . unwrap ( ) ;
311310
312- // we're over-estimating here, but slab doesn't expose its max index
311+ // This wait loop is exactly like the one in wait, except that if we find a reader that
312+ // has not observed the latest swap, we return rather than spin-and-retry.
313313 self . last_epochs . resize ( epochs. capacity ( ) , 0 ) ;
314314 for ( ri, epoch) in epochs. iter ( ) {
315315 if self . last_epochs [ ri] % 2 == 0 {
@@ -326,8 +326,13 @@ where
326326 return false ;
327327 }
328328 }
329- self . do_publish ( & mut epochs) ;
330- return true ;
329+ #[ cfg( test) ]
330+ {
331+ self . is_waiting . store ( false , Ordering :: Relaxed ) ;
332+ }
333+ self . update_and_swap ( & mut epochs) ;
334+
335+ true
331336 }
332337
333338 /// Publish all operations append to the log to reads.
@@ -349,11 +354,13 @@ where
349354
350355 self . wait ( & mut epochs) ;
351356
352- self . do_publish ( & mut epochs)
357+ self . update_and_swap ( & mut epochs)
353358 }
354359
355- /// Actual doing the publishing
356- fn do_publish (
360+ /// Brings `w_handle` up to date with the oplog, then swaps `r_handle` and `w_handle`.
361+ ///
362+ /// This method must only be called when all readers have exited `w_handle` (e.g., after `wait`)
363+ fn update_and_swap (
357364 & mut self ,
358365 epochs : & mut MutexGuard < ' _ , slab:: Slab < Arc < AtomicUsize > > > ,
359366 ) -> & mut Self {
@@ -766,7 +773,7 @@ mod tests {
766773 // Case 1: A reader has not advanced (odd and unchanged) -> returns false
767774 let mut epochs_slab = Slab :: new ( ) ;
768775 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
776+ // Ensure last_epochs sees this reader as odd and unchanged
770777 w. last_epochs = vec ! [ 0 ; epochs_slab. capacity( ) ] ;
771778 w. last_epochs [ idx] = 1 ;
772779 w. epochs = Arc :: new ( Mutex :: new ( epochs_slab) ) ;
0 commit comments