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