@@ -15,7 +15,7 @@ use tokio::sync::Notify;
1515/// This enum is used to declare whether you are enqueuing
1616/// or dequeuing an item for `acquire_shard_guard()`
1717#[ derive( Debug , PartialEq , Eq ) ]
18- pub enum Acquire {
18+ enum Acquire {
1919 Enqueue ,
2020 Dequeue ,
2121}
@@ -296,7 +296,8 @@ impl<T> CSShardedRingBuf<T> {
296296 /// - Dequeue: only returns None if the shard is *empty*
297297 ///
298298 /// Time Complexity: O(s_t) where s_t is how long it takes to acquire the shard
299- pub async fn acquire_shard_guard (
299+ #[ inline]
300+ async fn acquire_shard_guard (
300301 & self ,
301302 acquire : Acquire ,
302303 shard_ind : usize ,
@@ -346,14 +347,12 @@ impl<T> CSShardedRingBuf<T> {
346347 }
347348 if matches ! ( acquire, Acquire :: Dequeue ) {
348349 Some ( ShardLockGuard :: acquire_shard_guard (
349- acquire,
350350 & self . shard_locks [ shard_ind] ,
351351 & self . job_space_shard_notifs [ enq_shard_ind] ,
352352 & self . inner_rb [ shard_ind] ,
353353 ) )
354354 } else {
355355 Some ( ShardLockGuard :: acquire_shard_guard (
356- acquire,
357356 & self . shard_locks [ shard_ind] ,
358357 & self . job_post_shard_notifs [ shard_ind] ,
359358 & self . inner_rb [ shard_ind] ,
@@ -363,17 +362,14 @@ impl<T> CSShardedRingBuf<T> {
363362
364363 /// Given a `ShardLockGuard<'_, T>`, it enqueues an item inside the shard.
365364 ///
366- /// If a guard was obtained with the role of dequeuing, this function will panic.
365+ /// You must obtain a ShardLockGuard<'_, T> from either `enqueue_guard()`
366+ /// or `enqueue_guard_in_shard()`
367367 ///
368368 /// Time Complexity: O(1)
369369 ///
370370 /// Space Complexity: O(1)
371371 #[ inline( always) ]
372- pub fn enqueue_item ( & self , item : T , shard_guard : ShardLockGuard < ' _ , T > ) {
373- assert ! (
374- matches!( shard_guard. role, Acquire :: Enqueue ) ,
375- "You must acquire an Enqueue guard through 'enqueue_shard_guard()' or 'acquire_shard_guard' with Acquire::Enqueue."
376- ) ;
372+ pub fn enqueue ( & self , item : T , shard_guard : ShardLockGuard < ' _ , T > ) {
377373 let inner = shard_guard. shard ;
378374 // we use fetch add here because we want to obtain the previous value
379375 // to dequeue while also incrementing this counter (separate load and store
@@ -387,32 +383,43 @@ impl<T> CSShardedRingBuf<T> {
387383 }
388384 }
389385
390- /// Obtain a guard on a shard in the ring buffer for the purpose of enqueuing.
386+ /// Obtain a guard on a specific shard the ring buffer for the purpose of
387+ /// enqueuing.
388+ ///
389+ /// Returns None if the buffer was poisoned.
390+ ///
391+ /// Time Complexity: O(s_t) where s_t is the time it takes to acquire a shard
392+ ///
393+ /// Space complexity: O(1)
394+ #[ inline( always) ]
395+ pub async fn enqueue_guard_in_shard ( & self , shard_ind : usize ) -> Option < ShardLockGuard < ' _ , T > > {
396+ self . acquire_shard_guard ( Acquire :: Enqueue , shard_ind) . await
397+ }
398+
399+ /// Obtain a guard on a shard the ring buffer for the purpose of enqueuing.
400+ ///
391401 /// Returns None if the buffer was poisoned.
392402 ///
403+ /// Note: It obtains the shard in a circular manner, so for example, at the beginning,
404+ /// it obtains shard 0, then shard 1, the shard 2, ... (all modded with the number
405+ /// of shards that exists in this buffer)
406+ ///
393407 /// Time Complexity: O(s_t) where s_t is the time it takes to acquire a shard
394408 ///
395409 /// Space complexity: O(1)
396410 #[ inline( always) ]
397- pub async fn enqueue_shard_guard ( & self ) -> Option < ShardLockGuard < ' _ , T > > {
411+ pub async fn enqueue_guard ( & self ) -> Option < ShardLockGuard < ' _ , T > > {
398412 let shard_ind = self . shard_enq . fetch_add ( 1 , Ordering :: Relaxed ) % self . get_num_of_shards ( ) ;
399413 self . acquire_shard_guard ( Acquire :: Enqueue , shard_ind) . await
400414 }
401415
402416 /// Given a `ShardLockGuard<'_, T>`, it dequeues an item inside the shard.
403417 ///
404- /// If a guard was obtained with the role of enqueuing, this function will panic.
405- ///
406418 /// Time Complexity: O(1)
407419 ///
408420 /// Space Complexity: O(1)
409421 #[ inline( always) ]
410- pub fn dequeue_item ( & self , shard_guard : ShardLockGuard < ' _ , T > ) -> T {
411- assert ! (
412- matches!( shard_guard. role, Acquire :: Dequeue ) ,
413- "You must acquire a Dequeue guard through 'dequeue_shard_guard()' or 'acquire_shard_guard' with Acquire::Dequeue."
414- ) ;
415-
422+ fn dequeue_item ( & self , shard_guard : ShardLockGuard < ' _ , T > ) -> T {
416423 let inner = shard_guard. shard ;
417424 // we use fetch add here because we want to obtain the previous value
418425 // to dequeue while also incrementing this counter (separate load and store
@@ -422,16 +429,42 @@ impl<T> CSShardedRingBuf<T> {
422429 unsafe { ( * item_cell) . assume_init_read ( ) }
423430 }
424431
425- /// Obtain a guard on a shard in the ring buffer for the purpose of dequeuing.
432+ /// Performs both the operation of obtaining a guard on a shard in the ring buffer
433+ /// and dequeuing an item off from the buffer. This can be done like together because
434+ /// due to inherent cancellation safety (data either stays in buffer on cancellation
435+ /// or it gets taken out without touching an await point).
436+ ///
426437 /// Returns None if the buffer was poisoned and the shard contains no more items.
427438 ///
428439 /// Time Complexity: O(s_t) where s_t is the time it takes to acquire a shard
429440 ///
430441 /// Space Complexity: O(1)
431442 #[ inline( always) ]
432- pub async fn dequeue_shard_guard ( & self ) -> Option < ShardLockGuard < ' _ , T > > {
443+ pub async fn dequeue_in_shard ( & self , shard_ind : usize ) -> Option < T > {
444+ let shard_guard = self . acquire_shard_guard ( Acquire :: Dequeue , shard_ind) . await ;
445+ shard_guard. map ( |guard| self . dequeue_item ( guard) )
446+ }
447+
448+ /// Performs both the operation of obtaining a guard on a shard in the ring buffer
449+ /// and dequeuing an item off from the buffer. This can be done like together because
450+ /// due to inherent cancellation safety (data either stays in buffer on cancellation
451+ /// or it gets taken out without touching an await point).
452+ ///
453+ /// Returns None if the buffer was poisoned and the shard contains no more items.
454+ ///
455+ /// Note: It obtains the shard in a circular manner, so for example, at the beginning,
456+ /// it obtains shard 0, then shard 1, the shard 2, ... (all modded with the number
457+ /// of shards that exists in this buffer)
458+ ///
459+ /// Time Complexity: O(s_t) where s_t is the time it takes to acquire a shard
460+ ///
461+ /// Space Complexity: O(1)
462+ #[ inline( always) ]
463+ pub async fn dequeue ( & self ) -> Option < T > {
433464 let shard_ind = self . shard_deq . fetch_add ( 1 , Ordering :: Relaxed ) % self . get_num_of_shards ( ) ;
434- self . acquire_shard_guard ( Acquire :: Dequeue , shard_ind) . await
465+ let shard_guard = self . acquire_shard_guard ( Acquire :: Dequeue , shard_ind) . await ;
466+
467+ shard_guard. map ( |guard| self . dequeue_item ( guard) )
435468 }
436469
437470 /// Sets the poison flag of the ring buffer to true. This will prevent enqueuers
0 commit comments