@@ -18,23 +18,29 @@ use super::{Receiver, Sender};
1818pub ( crate ) type WaitQueueData = ( Waker , FreeSlotPtr ) ;
1919pub ( crate ) type WaitQueue = DoublyLinkedList < WaitQueueData > ;
2020
21+ #[ derive( Debug ) ]
22+ pub ( crate ) struct FreeSlot ( u8 ) ;
23+
2124/// A pointer to a free slot.
2225#[ derive( Clone ) ]
23- pub ( crate ) struct FreeSlotPtr ( * mut Option < u8 > ) ;
26+ pub ( crate ) struct FreeSlotPtr ( * mut Option < FreeSlot > ) ;
2427
2528impl FreeSlotPtr {
2629 /// SAFETY: `inner` must be valid until the [`Link`] containing this [`FreeSlotPtr`] is popped.
2730 /// Additionally, this [`FreeSlotPtr`] must have exclusive access to the data pointed to by
2831 /// `inner`.
29- pub unsafe fn new ( inner : * mut Option < u8 > ) -> Self {
32+ pub unsafe fn new ( inner : * mut Option < FreeSlot > ) -> Self {
3033 Self ( inner)
3134 }
3235
3336 /// Replace the value of this slot with `new_value`, and return
3437 /// the old value.
3538 ///
3639 /// SAFETY: the pointer in this [`FreeSlotPtr`] must be valid for writes.
37- pub ( crate ) unsafe fn take ( & mut self , cs : critical_section:: CriticalSection ) -> Option < u8 > {
40+ pub ( crate ) unsafe fn take (
41+ & mut self ,
42+ cs : critical_section:: CriticalSection ,
43+ ) -> Option < FreeSlot > {
3844 self . replace ( None , cs)
3945 }
4046
@@ -45,9 +51,9 @@ impl FreeSlotPtr {
4551 /// be obtained from `freeq`.
4652 unsafe fn replace (
4753 & mut self ,
48- new_value : Option < u8 > ,
54+ new_value : Option < FreeSlot > ,
4955 _cs : critical_section:: CriticalSection ,
50- ) -> Option < u8 > {
56+ ) -> Option < FreeSlot > {
5157 // SAFETY: we are in a critical section.
5258 unsafe { core:: ptr:: replace ( self . 0 , new_value) }
5359 }
@@ -147,31 +153,32 @@ impl<T, const N: usize> Channel<T, N> {
147153 ///
148154 /// This will do one of two things:
149155 /// 1. If there are any waiting `send`-ers, wake the longest-waiting one and hand it `slot`.
150- /// 2. else, insert `slot` into `self.freeq` .
156+ /// 2. else, insert `slot` into the free queue .
151157 ///
152- /// SAFETY: `slot` must be a `u8` that is obtained from [`Channel::readyq`] or through [`FreeSlotPtr::take`] .
153- pub ( crate ) unsafe fn push_free_slot ( & self , slot : u8 ) {
158+ /// SAFETY: `slot` must be obtained from this exact channel instance .
159+ pub ( crate ) unsafe fn return_free_slot ( & self , slot : FreeSlot ) {
154160 critical_section:: with ( |cs| {
155161 fence ( Ordering :: SeqCst ) ;
156162
157163 // If a sender is waiting in the `wait_queue`, wake the first one up & hand it the free slot.
158164 if let Some ( ( wait_head, mut freeq_slot) ) = self . wait_queue . pop ( ) {
159165 // SAFETY: `freeq_slot` is valid for writes: we are in a critical
160- // section & the `SlotPtr ` lives for at least the duration of the wait queue link.
166+ // section & the `FreeSlotPtr ` lives for at least the duration of the wait queue link.
161167 unsafe { freeq_slot. replace ( Some ( slot) , cs) } ;
162168 wait_head. wake ( ) ;
163169 } else {
164170 assert ! ( !self . access( cs) . freeq. is_full( ) ) ;
165- unsafe { self . access ( cs) . freeq . push_back_unchecked ( slot) }
171+ unsafe { self . access ( cs) . freeq . push_back_unchecked ( slot. 0 ) }
166172 }
167173 } ) ;
168174 }
169175
170- /// Push a value into a specific slot.
176+ /// Send a value using the given ` slot` in this channel .
171177 ///
172- /// SAFETY: `slot` must be obtained from [`Channel::pop_free_slot`] or through a popped [`SlotPtr`] .
178+ /// SAFETY: `slot` must be obtained from this exact channel instance .
173179 #[ inline( always) ]
174- pub ( crate ) unsafe fn slot_ready ( & self , slot : u8 , val : T ) {
180+ pub ( crate ) unsafe fn send_value ( & self , slot : FreeSlot , val : T ) {
181+ let slot = slot. 0 ;
175182 // Write the value to the slots, note; this memcpy is not under a critical section.
176183 unsafe { ptr:: write ( self . slots . get_unchecked ( slot as usize ) . get ( ) as * mut T , val) }
177184
@@ -187,16 +194,21 @@ impl<T, const N: usize> Channel<T, N> {
187194 self . receiver_waker . wake ( ) ;
188195 }
189196
190- /// Pop a ready slot.
191- pub ( crate ) fn pop_ready_slot ( & self ) -> Option < T > {
197+ /// Pop the value of a ready slot to make it available to a receiver.
198+ ///
199+ /// Internally, this function does these things:
200+ /// 1. Pop a ready slot from the ready queue.
201+ /// 2. If available, read the data from the backing slot storage.
202+ /// 3. If available, return the now-free slot to the free queue.
203+ pub ( crate ) fn receive_value ( & self ) -> Option < T > {
192204 let ready_slot = critical_section:: with ( |cs| self . access ( cs) . readyq . pop_front ( ) ) ;
193205
194206 if let Some ( rs) = ready_slot {
195207 let r = unsafe { ptr:: read ( self . slots . get_unchecked ( rs as usize ) . get ( ) as * const T ) } ;
196208
197209 // Return the index to the free queue after we've read the value.
198- // SAFETY: `rs` comes directly from `readyq` .
199- unsafe { self . push_free_slot ( rs ) } ;
210+ // SAFETY: `rs` is now a free slot obtained from this channel .
211+ unsafe { self . return_free_slot ( FreeSlot ( rs ) ) } ;
200212
201213 Some ( r)
202214 } else {
@@ -207,7 +219,7 @@ impl<T, const N: usize> Channel<T, N> {
207219 /// Register a new waiter in the wait queue.
208220 ///
209221 /// SAFETY: `link` must be valid until it is popped.
210- pub ( crate ) unsafe fn push_to_wait_queue ( & self , link : Pin < & Link < WaitQueueData > > ) {
222+ pub ( crate ) unsafe fn push_wait_queue ( & self , link : Pin < & Link < WaitQueueData > > ) {
211223 self . wait_queue . push ( link) ;
212224 }
213225
@@ -216,8 +228,9 @@ impl<T, const N: usize> Channel<T, N> {
216228 }
217229
218230 /// Pop a free slot.
219- pub ( crate ) fn pop_free_slot ( & self ) -> Option < u8 > {
220- critical_section:: with ( |cs| self . access ( cs) . freeq . pop_front ( ) )
231+ pub ( crate ) fn pop_free_slot ( & self ) -> Option < FreeSlot > {
232+ let slot = critical_section:: with ( |cs| self . access ( cs) . freeq . pop_front ( ) ) ;
233+ slot. map ( FreeSlot )
221234 }
222235
223236 pub ( crate ) fn num_senders ( & self ) -> usize {
0 commit comments