1#[macro_export]
49macro_rules! go {
50 ($body:expr) => {{
51 $crate::__spawn($body)
52 }};
53}
54
55#[macro_export]
86macro_rules! select {
87
88 ( recv($r:expr) -> $v:ident => $b:block $(,)? ) => {{
90 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
91 let mut __sel = ::std::vec![
92 $crate::select::recv_case_of(&($r), &mut __r0),
93 ];
94 $crate::select::selectgo(&mut __sel, false);
95 let $v = __r0;
96 $b
97 }};
98
99 ( recv($r:expr) -> $v:ident => $b:block $(,)? default => $d:block $(,)? ) => {{
101 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
102 let mut __sel = ::std::vec![
103 $crate::select::recv_case_of(&($r), &mut __r0),
104 ];
105 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
106 if __idx == 0 {
107 let $v = __r0;
108 $b
109 } else { $d }
110 }};
111
112 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
114 recv($r2:expr) -> $v2:ident => $b2:block $(,)? ) => {{
115 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
116 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
117 let mut __sel = ::std::vec![
118 $crate::select::recv_case_of(&($r1), &mut __r0),
119 $crate::select::recv_case_of(&($r2), &mut __r1),
120 ];
121 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
122 if __idx == 0 {
123 let $v1 = __r0;
124 $b1
125 } else {
126 let $v2 = __r1;
127 $b2
128 }
129 }};
130
131 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
133 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
134 default => $d:block $(,)? ) => {{
135 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
136 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
137 let mut __sel = ::std::vec![
138 $crate::select::recv_case_of(&($r1), &mut __r0),
139 $crate::select::recv_case_of(&($r2), &mut __r1),
140 ];
141 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
142 if __idx == 0 {
143 let $v1 = __r0;
144 $b1
145 } else if __idx == 1 {
146 let $v2 = __r1;
147 $b2
148 } else { $d }
149 }};
150
151 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
153 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
154 recv($r3:expr) -> $v3:ident => $b3:block $(,)? ) => {{
155 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
156 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
157 let mut __r2: ::std::option::Option<_> = ::std::option::Option::None;
158 let mut __sel = ::std::vec![
159 $crate::select::recv_case_of(&($r1), &mut __r0),
160 $crate::select::recv_case_of(&($r2), &mut __r1),
161 $crate::select::recv_case_of(&($r3), &mut __r2),
162 ];
163 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
164 if __idx == 0 {
165 let $v1 = __r0;
166 $b1
167 } else if __idx == 1 {
168 let $v2 = __r1;
169 $b2
170 } else {
171 let $v3 = __r2;
172 $b3
173 }
174 }};
175
176 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
178 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
179 recv($r3:expr) -> $v3:ident => $b3:block $(,)?
180 default => $d:block $(,)? ) => {{
181 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
182 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
183 let mut __r2: ::std::option::Option<_> = ::std::option::Option::None;
184 let mut __sel = ::std::vec![
185 $crate::select::recv_case_of(&($r1), &mut __r0),
186 $crate::select::recv_case_of(&($r2), &mut __r1),
187 $crate::select::recv_case_of(&($r3), &mut __r2),
188 ];
189 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
190 if __idx == 0 {
191 let $v1 = __r0;
192 $b1
193 } else if __idx == 1 {
194 let $v2 = __r1;
195 $b2
196 } else if __idx == 2 {
197 let $v3 = __r2;
198 $b3
199 } else { $d }
200 }};
201
202 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
204 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
205 recv($r3:expr) -> $v3:ident => $b3:block $(,)?
206 recv($r4:expr) -> $v4:ident => $b4:block $(,)? ) => {{
207 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
208 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
209 let mut __r2: ::std::option::Option<_> = ::std::option::Option::None;
210 let mut __r3: ::std::option::Option<_> = ::std::option::Option::None;
211 let mut __sel = ::std::vec![
212 $crate::select::recv_case_of(&($r1), &mut __r0),
213 $crate::select::recv_case_of(&($r2), &mut __r1),
214 $crate::select::recv_case_of(&($r3), &mut __r2),
215 $crate::select::recv_case_of(&($r4), &mut __r3),
216 ];
217 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
218 if __idx == 0 {
219 let $v1 = __r0;
220 $b1
221 } else if __idx == 1 {
222 let $v2 = __r1;
223 $b2
224 } else if __idx == 2 {
225 let $v3 = __r2;
226 $b3
227 } else {
228 let $v4 = __r3;
229 $b4
230 }
231 }};
232
233 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
235 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
236 recv($r3:expr) -> $v3:ident => $b3:block $(,)?
237 recv($r4:expr) -> $v4:ident => $b4:block $(,)?
238 default => $d:block $(,)? ) => {{
239 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
240 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
241 let mut __r2: ::std::option::Option<_> = ::std::option::Option::None;
242 let mut __r3: ::std::option::Option<_> = ::std::option::Option::None;
243 let mut __sel = ::std::vec![
244 $crate::select::recv_case_of(&($r1), &mut __r0),
245 $crate::select::recv_case_of(&($r2), &mut __r1),
246 $crate::select::recv_case_of(&($r3), &mut __r2),
247 $crate::select::recv_case_of(&($r4), &mut __r3),
248 ];
249 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
250 if __idx == 0 {
251 let $v1 = __r0;
252 $b1
253 } else if __idx == 1 {
254 let $v2 = __r1;
255 $b2
256 } else if __idx == 2 {
257 let $v3 = __r2;
258 $b3
259 } else if __idx == 3 {
260 let $v4 = __r3;
261 $b4
262 } else { $d }
263 }};
264
265 ( send($tx:expr, $sv:expr) => $sb:block $(,)? default => $d:block $(,)? ) => {{
267 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
268 let mut __sel = ::std::vec![
269 $crate::select::send_case_of(&($tx), &mut __s0),
270 ];
271 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
272 if __idx == 0 {
273 $sb
275 } else {
276 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
279 $d
280 }
281 }};
282
283 ( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
285 send($tx:expr, $sv:expr) => $sb:block $(,)? ) => {{
286 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
287 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
288 let mut __sel = ::std::vec![
289 $crate::select::recv_case_of(&($r1), &mut __r0),
290 $crate::select::send_case_of(&($tx), &mut __s0),
291 ];
292 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
293 if __idx == 0 {
294 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
296 let $v1 = __r0;
297 $rb
298 } else {
299 $sb
301 }
302 }};
303
304 ( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
306 send($tx:expr, $sv:expr) => $sb:block $(,)?
307 default => $d:block $(,)? ) => {{
308 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
309 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
310 let mut __sel = ::std::vec![
311 $crate::select::recv_case_of(&($r1), &mut __r0),
312 $crate::select::send_case_of(&($tx), &mut __s0),
313 ];
314 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
315 if __idx == 0 {
316 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
318 let $v1 = __r0;
319 $rb
320 } else if __idx == 1 {
321 $sb
322 } else {
323 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
325 $d
326 }
327 }};
328
329 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
331 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
332 send($tx:expr, $sv:expr) => $sb:block $(,)? ) => {{
333 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
334 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
335 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
336 let mut __sel = ::std::vec![
337 $crate::select::recv_case_of(&($r1), &mut __r0),
338 $crate::select::recv_case_of(&($r2), &mut __r1),
339 $crate::select::send_case_of(&($tx), &mut __s0),
340 ];
341 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
342 if __idx == 0 {
343 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
344 let $v1 = __r0;
345 $b1
346 } else if __idx == 1 {
347 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
348 let $v2 = __r1;
349 $b2
350 } else {
351 $sb
352 }
353 }};
354
355 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
357 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
358 send($tx:expr, $sv:expr) => $sb:block $(,)?
359 default => $d:block $(,)? ) => {{
360 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
361 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
362 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
363 let mut __sel = ::std::vec![
364 $crate::select::recv_case_of(&($r1), &mut __r0),
365 $crate::select::recv_case_of(&($r2), &mut __r1),
366 $crate::select::send_case_of(&($tx), &mut __s0),
367 ];
368 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
369 if __idx == 0 {
370 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
371 let $v1 = __r0;
372 $b1
373 } else if __idx == 1 {
374 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
375 let $v2 = __r1;
376 $b2
377 } else if __idx == 2 {
378 $sb
379 } else {
380 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
381 $d
382 }
383 }};
384
385 ( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
387 recv($r2:expr) -> $v2:ident => $b2:block $(,)?
388 recv($r3:expr) -> $v3:ident => $b3:block $(,)?
389 send($tx:expr, $sv:expr) => $sb:block $(,)? ) => {{
390 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
391 let mut __r1: ::std::option::Option<_> = ::std::option::Option::None;
392 let mut __r2: ::std::option::Option<_> = ::std::option::Option::None;
393 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
394 let mut __sel = ::std::vec![
395 $crate::select::recv_case_of(&($r1), &mut __r0),
396 $crate::select::recv_case_of(&($r2), &mut __r1),
397 $crate::select::recv_case_of(&($r3), &mut __r2),
398 $crate::select::send_case_of(&($tx), &mut __s0),
399 ];
400 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
401 if __idx == 0 {
402 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
403 let $v1 = __r0;
404 $b1
405 } else if __idx == 1 {
406 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
407 let $v2 = __r1;
408 $b2
409 } else if __idx == 2 {
410 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
411 let $v3 = __r2;
412 $b3
413 } else {
414 $sb
415 }
416 }};
417
418 ( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
420 send($tx1:expr, $sv1:expr) => $sb1:block $(,)?
421 send($tx2:expr, $sv2:expr) => $sb2:block $(,)? ) => {{
422 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
423 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv1);
424 let mut __s1: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv2);
425 let mut __sel = ::std::vec![
426 $crate::select::recv_case_of(&($r1), &mut __r0),
427 $crate::select::send_case_of(&($tx1), &mut __s0),
428 $crate::select::send_case_of(&($tx2), &mut __s1),
429 ];
430 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, false);
431 if __idx == 0 {
432 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0); ::std::mem::ManuallyDrop::drop(&mut __s1) };
433 let $v1 = __r0;
434 $rb
435 } else if __idx == 1 {
436 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s1) };
438 $sb1
439 } else {
440 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
442 $sb2
443 }
444 }};
445
446 ( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
448 send($tx1:expr, $sv1:expr) => $sb1:block $(,)?
449 send($tx2:expr, $sv2:expr) => $sb2:block $(,)?
450 default => $d:block $(,)? ) => {{
451 let mut __r0: ::std::option::Option<_> = ::std::option::Option::None;
452 let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv1);
453 let mut __s1: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv2);
454 let mut __sel = ::std::vec![
455 $crate::select::recv_case_of(&($r1), &mut __r0),
456 $crate::select::send_case_of(&($tx1), &mut __s0),
457 $crate::select::send_case_of(&($tx2), &mut __s1),
458 ];
459 let (__idx, _ok) = $crate::select::selectgo(&mut __sel, true);
460 if __idx == 0 {
461 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0); ::std::mem::ManuallyDrop::drop(&mut __s1) };
462 let $v1 = __r0;
463 $rb
464 } else if __idx == 1 {
465 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s1) };
466 $sb1
467 } else if __idx == 2 {
468 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
469 $sb2
470 } else {
471 unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0); ::std::mem::ManuallyDrop::drop(&mut __s1) };
472 $d
473 }
474 }};
475}
476
477#[cfg(all(test, not(loom)))]
482mod tests {
483 use crate::chan::chan;
484 use crate::runtime::sched::run_impl;
485 use std::sync::atomic::{AtomicI32, Ordering};
486 use std::sync::Arc;
487
488 #[test]
492 fn go_macro_spawns() {
493 let count = Arc::new(AtomicI32::new(0));
494 let c2 = Arc::clone(&count);
495 run_impl(move || {
496 go!(move || { c2.fetch_add(1, Ordering::Relaxed); });
497 for _ in 0..50 { crate::gosched(); }
499 });
500 assert_eq!(count.load(Ordering::Acquire), 1);
501 }
502
503 #[test]
507 fn select_recv_default_data_ready() {
508 run_impl(|| {
509 let (tx, rx) = chan::<i32>(1);
510 tx.send(7);
511 select! {
512 recv(rx) -> v => { assert_eq!(v.unwrap(), 7); }
513 default => { panic!("default should not fire"); }
514 }
515 });
516 }
517
518 #[test]
520 fn select_default_when_empty() {
521 run_impl(|| {
522 let (_tx, rx) = chan::<i32>(1);
523 select! {
524 recv(rx) -> _v => { panic!("should not recv"); }
525 default => {} }
527 });
528 }
529
530 #[test]
532 fn select_two_recv_first_ready() {
533 run_impl(|| {
534 let (tx1, rx1) = chan::<i32>(1);
535 let (_tx2, rx2) = chan::<i32>(1);
536 tx1.send(42);
537 select! {
538 recv(rx1) -> v => { assert_eq!(v.unwrap(), 42); }
539 recv(rx2) -> _v => { panic!("rx2 should not fire"); }
540 default => { panic!("unexpected default — rx1 should have been ready"); }
541 }
542 });
543 }
544
545 #[test]
547 fn select_send_default_space_available() {
548 run_impl(|| {
549 let (tx, rx) = chan::<i32>(1);
550 select! {
551 send(tx, 99_i32) => {} default => { panic!("default should not fire"); }
553 }
554 assert_eq!(rx.recv(), Some(99));
555 });
556 }
557
558 #[test]
560 fn select_send_default_buffer_full() {
561 run_impl(|| {
562 let (tx, rx) = chan::<i32>(1);
563 tx.send(1); select! {
565 send(tx, 2_i32) => { panic!("should not send — buffer is full"); }
566 default => {} }
568 assert_eq!(rx.recv(), Some(1));
569 });
570 }
571
572 #[test]
575 fn select_recv_send_default() {
576 run_impl(|| {
577 let (tx1, rx1) = chan::<i32>(1);
578 let (tx2, rx2) = chan::<i32>(1);
579 tx1.send(10);
580 let mut recv_val = -1_i32;
581 let mut send_ok = false;
582 select! {
584 recv(rx1) -> v => { recv_val = v.unwrap(); }
585 send(tx2, 20_i32) => { send_ok = true; }
586 default => {}
587 }
588 assert!(recv_val == 10 || send_ok);
590 let _ = rx2.try_recv(); });
592 }
593
594 #[test]
598 fn select_blocking_recv() {
599 let result = Arc::new(AtomicI32::new(-1));
600 let r2 = Arc::clone(&result);
601 run_impl(move || {
602 let (tx, rx) = chan::<i32>(0);
603 go!(move || { tx.send(55); });
604 select! {
605 recv(rx) -> v => { r2.store(v.unwrap(), Ordering::Relaxed); }
606 }
607 });
608 assert_eq!(result.load(Ordering::Acquire), 55);
609 }
610
611 #[test]
613 fn select_blocking_two_recv() {
614 let winner = Arc::new(AtomicI32::new(-1));
615 let w2 = Arc::clone(&winner);
616 run_impl(move || {
617 let (tx1, rx1) = chan::<i32>(0);
618 let (tx2, rx2) = chan::<i32>(0);
619 go!(move || { tx1.send(1); });
620 go!(move || { tx2.send(2); });
621 select! {
622 recv(rx1) -> v => { w2.store(v.unwrap(), Ordering::Relaxed); }
623 recv(rx2) -> v => { w2.store(v.unwrap(), Ordering::Relaxed); }
624 }
625 });
626 let w = winner.load(Ordering::Acquire);
627 assert!(w == 1 || w == 2, "winner should be 1 or 2, got {w}");
628 }
629
630 #[test]
632 fn select_blocking_recv_send() {
633 let recv_val = Arc::new(AtomicI32::new(-1));
634 let rv2 = Arc::clone(&recv_val);
635 run_impl(move || {
636 let (tx1, rx1) = chan::<i32>(0); let (tx2, rx2) = chan::<i32>(0); go!(move || { tx1.send(77); });
640 go!(move || {
642 crate::gosched();
644 let _ = rx2.recv();
645 });
646 select! {
647 recv(rx1) -> v => { rv2.store(v.unwrap(), Ordering::Relaxed); }
648 send(tx2, 99_i32) => {}
649 }
650 });
651 let v = recv_val.load(Ordering::Acquire);
653 assert!(v == 77 || v == -1, "unexpected value {v}");
654 }
655
656 #[test]
658 fn select_recv_closed_yields_none() {
659 run_impl(|| {
660 let (tx, rx) = chan::<i32>(0);
661 tx.close();
662 select! {
663 recv(rx) -> v => { assert!(v.is_none(), "should be None for closed channel"); }
664 }
665 });
666 }
667}