@@ -55,6 +55,23 @@ unsafe impl<T, const N: usize> Send for Channel<T, N> {}
55
55
56
56
unsafe impl < T , const N : usize > Sync for Channel < T , N > { }
57
57
58
+ macro_rules! cs_access {
59
+ ( $name: ident, $type: ty) => {
60
+ /// Access the value mutably.
61
+ ///
62
+ /// SAFETY: this function must not be called recursively within `f`.
63
+ unsafe fn $name<F , R >( & self , _cs: critical_section:: CriticalSection , f: F ) -> R
64
+ where
65
+ F : FnOnce ( & mut $type) -> R ,
66
+ {
67
+ self . $name. with_mut( |v| {
68
+ let v = unsafe { & mut * v } ;
69
+ f( v)
70
+ } )
71
+ }
72
+ } ;
73
+ }
74
+
58
75
impl < T , const N : usize > Channel < T , N > {
59
76
const _CHECK: ( ) = assert ! ( N < 256 , "This queue support a maximum of 255 entries" ) ;
60
77
@@ -113,45 +130,10 @@ impl<T, const N: usize> Channel<T, N> {
113
130
( Sender ( self ) , Receiver ( self ) )
114
131
}
115
132
116
- fn freeq < F , R > ( & self , _cs : critical_section:: CriticalSection , f : F ) -> R
117
- where
118
- F : FnOnce ( & mut Deque < u8 , N > ) -> R ,
119
- {
120
- self . freeq . with_mut ( |freeq| {
121
- let queue = unsafe { & mut * freeq } ;
122
- f ( queue)
123
- } )
124
- }
125
-
126
- fn readyq < F , R > ( & self , _cs : critical_section:: CriticalSection , f : F ) -> R
127
- where
128
- F : FnOnce ( & mut Deque < u8 , N > ) -> R ,
129
- {
130
- self . readyq . with_mut ( |readyq| {
131
- let queue = unsafe { & mut * readyq } ;
132
- f ( queue)
133
- } )
134
- }
135
-
136
- fn receiver_dropped < F , R > ( & self , _cs : critical_section:: CriticalSection , f : F ) -> R
137
- where
138
- F : FnOnce ( & mut bool ) -> R ,
139
- {
140
- self . receiver_dropped . with_mut ( |receiver_dropped| {
141
- let receiver_dropped = unsafe { & mut * receiver_dropped } ;
142
- f ( receiver_dropped)
143
- } )
144
- }
145
-
146
- fn num_senders < F , R > ( & self , _cs : critical_section:: CriticalSection , f : F ) -> R
147
- where
148
- F : FnOnce ( & mut usize ) -> R ,
149
- {
150
- self . num_senders . with_mut ( |num_senders| {
151
- let num_senders = unsafe { & mut * num_senders } ;
152
- f ( num_senders)
153
- } )
154
- }
133
+ cs_access ! ( freeq, Deque <u8 , N >) ;
134
+ cs_access ! ( readyq, Deque <u8 , N >) ;
135
+ cs_access ! ( receiver_dropped, bool ) ;
136
+ cs_access ! ( num_senders, usize ) ;
155
137
}
156
138
157
139
/// Creates a split channel with `'static` lifetime.R
@@ -276,7 +258,8 @@ impl<T, const N: usize> Sender<'_, T, N> {
276
258
277
259
// Write the value into the ready queue.
278
260
critical_section:: with ( |cs| {
279
- assert ! ( !self . 0 . readyq( cs, |q| q. is_full( ) ) ) ;
261
+ // SAFETY: the closure does not call `readyq`
262
+ assert ! ( unsafe { !self . 0 . readyq( cs, |q| q. is_full( ) ) } ) ;
280
263
unsafe { self . 0 . readyq ( cs, |q| q. push_back_unchecked ( idx) ) }
281
264
} ) ;
282
265
@@ -298,12 +281,14 @@ impl<T, const N: usize> Sender<'_, T, N> {
298
281
return Err ( TrySendError :: NoReceiver ( val) ) ;
299
282
}
300
283
301
- let idx =
302
- if let Some ( idx) = critical_section:: with ( |cs| self . 0 . freeq ( cs, |q| q. pop_front ( ) ) ) {
303
- idx
304
- } else {
305
- return Err ( TrySendError :: Full ( val) ) ;
306
- } ;
284
+ // SAFETY: the closure does not call `freeq`
285
+ let idx = if let Some ( idx) =
286
+ critical_section:: with ( |cs| unsafe { self . 0 . freeq ( cs, |q| q. pop_front ( ) ) } )
287
+ {
288
+ idx
289
+ } else {
290
+ return Err ( TrySendError :: Full ( val) ) ;
291
+ } ;
307
292
308
293
self . send_footer ( idx, val) ;
309
294
@@ -337,7 +322,8 @@ impl<T, const N: usize> Sender<'_, T, N> {
337
322
// Do all this in one critical section, else there can be race conditions
338
323
let queue_idx = critical_section:: with ( |cs| {
339
324
let wq_empty = self . 0 . wait_queue . is_empty ( ) ;
340
- let fq_empty = self . 0 . freeq ( cs, |q| q. is_empty ( ) ) ;
325
+ // SAFETY: the closure does not call `freeq`
326
+ let fq_empty = unsafe { self . 0 . freeq ( cs, |q| q. is_empty ( ) ) } ;
341
327
342
328
if !wq_empty || fq_empty {
343
329
// SAFETY: This pointer is only dereferenced here and on drop of the future
@@ -365,7 +351,8 @@ impl<T, const N: usize> Sender<'_, T, N> {
365
351
}
366
352
}
367
353
368
- assert ! ( !self . 0 . freeq( cs, |q| q. is_empty( ) ) ) ;
354
+ // SAFETY: the closure does not call `freeq`
355
+ assert ! ( unsafe { !self . 0 . freeq( cs, |q| q. is_empty( ) ) } ) ;
369
356
// Get index as the queue is guaranteed not empty and the wait queue is empty
370
357
let idx = unsafe { self . 0 . freeq ( cs, |q| q. pop_front_unchecked ( ) ) } ;
371
358
@@ -395,28 +382,34 @@ impl<T, const N: usize> Sender<'_, T, N> {
395
382
396
383
/// Returns true if there is no `Receiver`s.
397
384
pub fn is_closed ( & self ) -> bool {
398
- critical_section:: with ( |cs| self . 0 . receiver_dropped ( cs, |v| * v) )
385
+ // SAFETY: the closure does not call `receiver_dropped`
386
+ critical_section:: with ( |cs| unsafe { self . 0 . receiver_dropped ( cs, |v| * v) } )
399
387
}
400
388
401
389
/// Is the queue full.
402
390
pub fn is_full ( & self ) -> bool {
403
- critical_section:: with ( |cs| self . 0 . freeq ( cs, |q| q. is_empty ( ) ) )
391
+ // SAFETY: the closure does not call `freeq`
392
+ critical_section:: with ( |cs| unsafe { self . 0 . freeq ( cs, |q| q. is_empty ( ) ) } )
404
393
}
405
394
406
395
/// Is the queue empty.
407
396
pub fn is_empty ( & self ) -> bool {
408
- critical_section:: with ( |cs| self . 0 . freeq ( cs, |q| q. is_full ( ) ) )
397
+ // SAFETY: the closure does not call `freeq`
398
+ critical_section:: with ( |cs| unsafe { self . 0 . freeq ( cs, |q| q. is_full ( ) ) } )
409
399
}
410
400
}
411
401
412
402
impl < T , const N : usize > Drop for Sender < ' _ , T , N > {
413
403
fn drop ( & mut self ) {
414
404
// Count down the reference counter
415
405
let num_senders = critical_section:: with ( |cs| {
416
- self . 0 . num_senders ( cs, |v| {
417
- * v -= 1 ;
418
- * v
419
- } )
406
+ // SAFETY: the closure does not call `num_senders`
407
+ unsafe {
408
+ self . 0 . num_senders ( cs, |v| {
409
+ * v -= 1 ;
410
+ * v
411
+ } )
412
+ }
420
413
} ) ;
421
414
422
415
// If there are no senders, wake the receiver to do error handling.
@@ -429,7 +422,8 @@ impl<T, const N: usize> Drop for Sender<'_, T, N> {
429
422
impl < T , const N : usize > Clone for Sender < ' _ , T , N > {
430
423
fn clone ( & self ) -> Self {
431
424
// Count up the reference counter
432
- critical_section:: with ( |cs| self . 0 . num_senders ( cs, |v| * v += 1 ) ) ;
425
+ // SAFETY: the closure does not call `num_senders`
426
+ critical_section:: with ( |cs| unsafe { self . 0 . num_senders ( cs, |v| * v += 1 ) } ) ;
433
427
434
428
Self ( self . 0 )
435
429
}
@@ -469,7 +463,10 @@ impl<T, const N: usize> Receiver<'_, T, N> {
469
463
/// Receives a value if there is one in the channel, non-blocking.
470
464
pub fn try_recv ( & mut self ) -> Result < T , ReceiveError > {
471
465
// Try to get a ready slot.
472
- let ready_slot = critical_section:: with ( |cs| self . 0 . readyq ( cs, |q| q. pop_front ( ) ) ) ;
466
+ let ready_slot = critical_section:: with ( |cs| {
467
+ // SAFETY: the closure does not call `readyq`.
468
+ unsafe { self . 0 . readyq ( cs, |q| q. pop_front ( ) ) }
469
+ } ) ;
473
470
474
471
if let Some ( rs) = ready_slot {
475
472
// Read the value from the slots, note; this memcpy is not under a critical section.
@@ -480,10 +477,14 @@ impl<T, const N: usize> Receiver<'_, T, N> {
480
477
481
478
// Return the index to the free queue after we've read the value.
482
479
critical_section:: with ( |cs| {
483
- self . 0 . freeq ( cs, |freeq| {
484
- assert ! ( !freeq. is_full( ) ) ;
485
- unsafe { freeq. push_back_unchecked ( rs) }
486
- } ) ;
480
+ // SAFETY: the closure does not call `freeq`
481
+ unsafe {
482
+ self . 0 . freeq ( cs, |freeq| {
483
+ assert ! ( !freeq. is_full( ) ) ;
484
+ // SAFETY: `freeq` is not full.
485
+ freeq. push_back_unchecked ( rs)
486
+ } ) ;
487
+ }
487
488
488
489
fence ( Ordering :: SeqCst ) ;
489
490
@@ -528,24 +529,36 @@ impl<T, const N: usize> Receiver<'_, T, N> {
528
529
529
530
/// Returns true if there are no `Sender`s.
530
531
pub fn is_closed ( & self ) -> bool {
531
- critical_section:: with ( |cs| self . 0 . num_senders ( cs, |v| * v == 0 ) )
532
+ critical_section:: with ( |cs| {
533
+ // SAFETY: the closure does not call `num_senders`
534
+ unsafe { self . 0 . num_senders ( cs, |v| * v == 0 ) }
535
+ } )
532
536
}
533
537
534
538
/// Is the queue full.
535
539
pub fn is_full ( & self ) -> bool {
536
- critical_section:: with ( |cs| self . 0 . readyq ( cs, |q| q. is_full ( ) ) )
540
+ critical_section:: with ( |cs| {
541
+ // SAFETY: the closure does not call `readyq`
542
+ unsafe { self . 0 . readyq ( cs, |q| q. is_full ( ) ) }
543
+ } )
537
544
}
538
545
539
546
/// Is the queue empty.
540
547
pub fn is_empty ( & self ) -> bool {
541
- critical_section:: with ( |cs| self . 0 . readyq ( cs, |q| q. is_empty ( ) ) )
548
+ critical_section:: with ( |cs| {
549
+ // SAFETY: the closure does not call `readyq`
550
+ unsafe { self . 0 . readyq ( cs, |q| q. is_empty ( ) ) }
551
+ } )
542
552
}
543
553
}
544
554
545
555
impl < T , const N : usize > Drop for Receiver < ' _ , T , N > {
546
556
fn drop ( & mut self ) {
547
557
// Mark the receiver as dropped and wake all waiters
548
- critical_section:: with ( |cs| self . 0 . receiver_dropped ( cs, |v| * v = true ) ) ;
558
+ critical_section:: with ( |cs| {
559
+ // SAFETY: the closure does not call `receiver_dropped`
560
+ unsafe { self . 0 . receiver_dropped ( cs, |v| * v = true ) }
561
+ } ) ;
549
562
550
563
while let Some ( waker) = self . 0 . wait_queue . pop ( ) {
551
564
waker. wake ( ) ;
0 commit comments