crossbeam_channel/flavors/
zero.rs1use std::boxed::Box;
6use std::cell::UnsafeCell;
7use std::marker::PhantomData;
8use std::sync::atomic::{AtomicBool, Ordering};
9use std::time::Instant;
10use std::{fmt, ptr};
11
12use crossbeam_utils::Backoff;
13
14use crate::context::Context;
15use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
16use crate::select::{Operation, SelectHandle, Selected, Token};
17use crate::utils::Mutex;
18use crate::waker::Waker;
19
20pub(crate) struct ZeroToken(*mut ());
22
23impl Default for ZeroToken {
24 fn default() -> Self {
25 Self(ptr::null_mut())
26 }
27}
28
29impl fmt::Debug for ZeroToken {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 fmt::Debug::fmt(&(self.0 as usize), f)
32 }
33}
34
35struct Packet<T> {
37 on_stack: bool,
39
40 ready: AtomicBool,
42
43 msg: UnsafeCell<Option<T>>,
45}
46
47impl<T> Packet<T> {
48 fn empty_on_stack() -> Packet<T> {
50 Packet {
51 on_stack: true,
52 ready: AtomicBool::new(false),
53 msg: UnsafeCell::new(None),
54 }
55 }
56
57 fn empty_on_heap() -> Box<Packet<T>> {
59 Box::new(Packet {
60 on_stack: false,
61 ready: AtomicBool::new(false),
62 msg: UnsafeCell::new(None),
63 })
64 }
65
66 fn message_on_stack(msg: T) -> Packet<T> {
68 Packet {
69 on_stack: true,
70 ready: AtomicBool::new(false),
71 msg: UnsafeCell::new(Some(msg)),
72 }
73 }
74
75 fn wait_ready(&self) {
77 let backoff = Backoff::new();
78 while !self.ready.load(Ordering::Acquire) {
79 backoff.snooze();
80 }
81 }
82}
83
84struct Inner {
86 senders: Waker,
88
89 receivers: Waker,
91
92 is_disconnected: bool,
94}
95
96pub(crate) struct Channel<T> {
98 inner: Mutex<Inner>,
100
101 _marker: PhantomData<T>,
103}
104
105impl<T> Channel<T> {
106 pub(crate) fn new() -> Self {
108 Channel {
109 inner: Mutex::new(Inner {
110 senders: Waker::new(),
111 receivers: Waker::new(),
112 is_disconnected: false,
113 }),
114 _marker: PhantomData,
115 }
116 }
117
118 pub(crate) fn receiver(&self) -> Receiver<'_, T> {
120 Receiver(self)
121 }
122
123 pub(crate) fn sender(&self) -> Sender<'_, T> {
125 Sender(self)
126 }
127
128 fn start_send(&self, token: &mut Token) -> bool {
130 let mut inner = self.inner.lock();
131
132 if let Some(operation) = inner.receivers.try_select() {
134 token.zero.0 = operation.packet;
135 true
136 } else if inner.is_disconnected {
137 token.zero.0 = ptr::null_mut();
138 true
139 } else {
140 false
141 }
142 }
143
144 pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
146 if token.zero.0.is_null() {
148 return Err(msg);
149 }
150
151 let packet = &*(token.zero.0 as *const Packet<T>);
152 packet.msg.get().write(Some(msg));
153 packet.ready.store(true, Ordering::Release);
154 Ok(())
155 }
156
157 fn start_recv(&self, token: &mut Token) -> bool {
159 let mut inner = self.inner.lock();
160
161 if let Some(operation) = inner.senders.try_select() {
163 token.zero.0 = operation.packet;
164 true
165 } else if inner.is_disconnected {
166 token.zero.0 = ptr::null_mut();
167 true
168 } else {
169 false
170 }
171 }
172
173 pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
175 if token.zero.0.is_null() {
177 return Err(());
178 }
179
180 let packet = &*(token.zero.0 as *const Packet<T>);
181
182 if packet.on_stack {
183 let msg = packet.msg.get().replace(None).unwrap();
187 packet.ready.store(true, Ordering::Release);
188 Ok(msg)
189 } else {
190 packet.wait_ready();
193 let msg = packet.msg.get().replace(None).unwrap();
194 drop(Box::from_raw(token.zero.0.cast::<Packet<T>>()));
195 Ok(msg)
196 }
197 }
198
199 pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
201 let token = &mut Token::default();
202 let mut inner = self.inner.lock();
203
204 if let Some(operation) = inner.receivers.try_select() {
206 token.zero.0 = operation.packet;
207 drop(inner);
208 unsafe {
209 self.write(token, msg).ok().unwrap();
210 }
211 Ok(())
212 } else if inner.is_disconnected {
213 Err(TrySendError::Disconnected(msg))
214 } else {
215 Err(TrySendError::Full(msg))
216 }
217 }
218
219 pub(crate) fn send(
221 &self,
222 msg: T,
223 deadline: Option<Instant>,
224 ) -> Result<(), SendTimeoutError<T>> {
225 let token = &mut Token::default();
226 let mut inner = self.inner.lock();
227
228 if let Some(operation) = inner.receivers.try_select() {
230 token.zero.0 = operation.packet;
231 drop(inner);
232 unsafe {
233 self.write(token, msg).ok().unwrap();
234 }
235 return Ok(());
236 }
237
238 if inner.is_disconnected {
239 return Err(SendTimeoutError::Disconnected(msg));
240 }
241
242 Context::with(|cx| {
243 let oper = Operation::hook(token);
245 let mut packet = Packet::<T>::message_on_stack(msg);
246 inner
247 .senders
248 .register_with_packet(oper, &mut packet as *mut Packet<T> as *mut (), cx);
249 inner.receivers.notify();
250 drop(inner);
251
252 let sel = cx.wait_until(deadline);
254
255 match sel {
256 Selected::Waiting => unreachable!(),
257 Selected::Aborted => {
258 self.inner.lock().senders.unregister(oper).unwrap();
259 let msg = unsafe { packet.msg.get().replace(None).unwrap() };
260 Err(SendTimeoutError::Timeout(msg))
261 }
262 Selected::Disconnected => {
263 self.inner.lock().senders.unregister(oper).unwrap();
264 let msg = unsafe { packet.msg.get().replace(None).unwrap() };
265 Err(SendTimeoutError::Disconnected(msg))
266 }
267 Selected::Operation(_) => {
268 packet.wait_ready();
270 Ok(())
271 }
272 }
273 })
274 }
275
276 pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
278 let token = &mut Token::default();
279 let mut inner = self.inner.lock();
280
281 if let Some(operation) = inner.senders.try_select() {
283 token.zero.0 = operation.packet;
284 drop(inner);
285 unsafe { self.read(token).map_err(|_| TryRecvError::Disconnected) }
286 } else if inner.is_disconnected {
287 Err(TryRecvError::Disconnected)
288 } else {
289 Err(TryRecvError::Empty)
290 }
291 }
292
293 pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
295 let token = &mut Token::default();
296 let mut inner = self.inner.lock();
297
298 if let Some(operation) = inner.senders.try_select() {
300 token.zero.0 = operation.packet;
301 drop(inner);
302 unsafe {
303 return self.read(token).map_err(|_| RecvTimeoutError::Disconnected);
304 }
305 }
306
307 if inner.is_disconnected {
308 return Err(RecvTimeoutError::Disconnected);
309 }
310
311 Context::with(|cx| {
312 let oper = Operation::hook(token);
314 let mut packet = Packet::<T>::empty_on_stack();
315 inner.receivers.register_with_packet(
316 oper,
317 &mut packet as *mut Packet<T> as *mut (),
318 cx,
319 );
320 inner.senders.notify();
321 drop(inner);
322
323 let sel = cx.wait_until(deadline);
325
326 match sel {
327 Selected::Waiting => unreachable!(),
328 Selected::Aborted => {
329 self.inner.lock().receivers.unregister(oper).unwrap();
330 Err(RecvTimeoutError::Timeout)
331 }
332 Selected::Disconnected => {
333 self.inner.lock().receivers.unregister(oper).unwrap();
334 Err(RecvTimeoutError::Disconnected)
335 }
336 Selected::Operation(_) => {
337 packet.wait_ready();
339 unsafe { Ok(packet.msg.get().replace(None).unwrap()) }
340 }
341 }
342 })
343 }
344
345 pub(crate) fn disconnect(&self) -> bool {
349 let mut inner = self.inner.lock();
350
351 if !inner.is_disconnected {
352 inner.is_disconnected = true;
353 inner.senders.disconnect();
354 inner.receivers.disconnect();
355 true
356 } else {
357 false
358 }
359 }
360
361 pub(crate) fn len(&self) -> usize {
363 0
364 }
365
366 pub(crate) fn capacity(&self) -> Option<usize> {
368 Some(0)
369 }
370
371 pub(crate) fn is_empty(&self) -> bool {
373 true
374 }
375
376 pub(crate) fn is_full(&self) -> bool {
378 true
379 }
380}
381
382pub(crate) struct Receiver<'a, T>(&'a Channel<T>);
384
385pub(crate) struct Sender<'a, T>(&'a Channel<T>);
387
388impl<T> SelectHandle for Receiver<'_, T> {
389 fn try_select(&self, token: &mut Token) -> bool {
390 self.0.start_recv(token)
391 }
392
393 fn deadline(&self) -> Option<Instant> {
394 None
395 }
396
397 fn register(&self, oper: Operation, cx: &Context) -> bool {
398 let packet = Box::into_raw(Packet::<T>::empty_on_heap());
399
400 let mut inner = self.0.inner.lock();
401 inner
402 .receivers
403 .register_with_packet(oper, packet.cast::<()>(), cx);
404 inner.senders.notify();
405 inner.senders.can_select() || inner.is_disconnected
406 }
407
408 fn unregister(&self, oper: Operation) {
409 if let Some(operation) = self.0.inner.lock().receivers.unregister(oper) {
410 unsafe {
411 drop(Box::from_raw(operation.packet.cast::<Packet<T>>()));
412 }
413 }
414 }
415
416 fn accept(&self, token: &mut Token, cx: &Context) -> bool {
417 token.zero.0 = cx.wait_packet();
418 true
419 }
420
421 fn is_ready(&self) -> bool {
422 let inner = self.0.inner.lock();
423 inner.senders.can_select() || inner.is_disconnected
424 }
425
426 fn watch(&self, oper: Operation, cx: &Context) -> bool {
427 let mut inner = self.0.inner.lock();
428 inner.receivers.watch(oper, cx);
429 inner.senders.can_select() || inner.is_disconnected
430 }
431
432 fn unwatch(&self, oper: Operation) {
433 let mut inner = self.0.inner.lock();
434 inner.receivers.unwatch(oper);
435 }
436}
437
438impl<T> SelectHandle for Sender<'_, T> {
439 fn try_select(&self, token: &mut Token) -> bool {
440 self.0.start_send(token)
441 }
442
443 fn deadline(&self) -> Option<Instant> {
444 None
445 }
446
447 fn register(&self, oper: Operation, cx: &Context) -> bool {
448 let packet = Box::into_raw(Packet::<T>::empty_on_heap());
449
450 let mut inner = self.0.inner.lock();
451 inner
452 .senders
453 .register_with_packet(oper, packet.cast::<()>(), cx);
454 inner.receivers.notify();
455 inner.receivers.can_select() || inner.is_disconnected
456 }
457
458 fn unregister(&self, oper: Operation) {
459 if let Some(operation) = self.0.inner.lock().senders.unregister(oper) {
460 unsafe {
461 drop(Box::from_raw(operation.packet.cast::<Packet<T>>()));
462 }
463 }
464 }
465
466 fn accept(&self, token: &mut Token, cx: &Context) -> bool {
467 token.zero.0 = cx.wait_packet();
468 true
469 }
470
471 fn is_ready(&self) -> bool {
472 let inner = self.0.inner.lock();
473 inner.receivers.can_select() || inner.is_disconnected
474 }
475
476 fn watch(&self, oper: Operation, cx: &Context) -> bool {
477 let mut inner = self.0.inner.lock();
478 inner.senders.watch(oper, cx);
479 inner.receivers.can_select() || inner.is_disconnected
480 }
481
482 fn unwatch(&self, oper: Operation) {
483 let mut inner = self.0.inner.lock();
484 inner.senders.unwatch(oper);
485 }
486}