maniac_runtime/generator/
yield_.rs1use std::any::Any;
6use std::sync::atomic;
7
8use crate::generator::gen_impl::{unlikely, Generator};
9use crate::generator::reg_context::RegContext;
10use crate::generator::rt::{is_generator, Context, ContextStack, Error};
11
12#[macro_export]
15macro_rules! done {
16 () => {{
17 return crate::generator::done();
18 }};
19}
20
21#[doc(hidden)]
24#[inline]
25pub fn done<T>() -> T {
26 assert!(is_generator(), "done is only possible in a generator");
27 std::panic::panic_any(Error::Done)
28}
29
30#[inline]
32pub fn yield_now() {
33 let env = ContextStack::current();
34 let cur = env.top();
35 raw_yield_now(&env, cur);
36}
37
38#[inline]
39pub fn raw_yield_now(env: &ContextStack, cur: &mut Context) {
40 let parent = env.pop_context(cur as *mut _);
41 RegContext::swap(&mut cur.regs, &parent.regs);
42}
43
44#[inline]
46fn raw_yield<T: Any>(env: &ContextStack, context: &mut Context, v: T) {
47 if unlikely(!context.is_generator()) {
49 panic!("yield from none generator context");
50 }
51
52 context.set_ret(v);
53 context._ref -= 1;
54 raw_yield_now(env, context);
55
56 if unlikely(context._ref != 1) {
58 std::panic::panic_any(Error::Cancel);
59 }
60}
61
62#[inline]
64#[deprecated(since = "0.6.18", note = "please use `scope` version instead")]
65pub fn yield_with<T: Any>(v: T) {
66 let env = ContextStack::current();
67 let context = env.top();
68 raw_yield(&env, context, v);
69}
70
71#[inline]
73#[deprecated(since = "0.6.18", note = "please use `scope` version instead")]
74pub fn get_yield<A: Any>() -> Option<A> {
75 let context = ContextStack::current().top();
76 raw_get_yield(context)
77}
78
79#[inline]
81fn raw_get_yield<A: Any>(context: &mut Context) -> Option<A> {
82 if unlikely(!context.is_generator()) {
84 {
85 log::error!("get yield from none generator context");
86 std::panic::panic_any(Error::ContextErr);
87 }
88 }
89
90 context.get_para()
91}
92
93#[inline]
98#[deprecated(since = "0.6.18", note = "please use `scope` version instead")]
99pub fn yield_<A: Any, T: Any>(v: T) -> Option<A> {
100 let env = ContextStack::current();
101 let context = env.top();
102 raw_yield(&env, context, v);
103 atomic::compiler_fence(atomic::Ordering::Acquire);
104 raw_get_yield(context)
105}
106
107#[deprecated(since = "0.6.18", note = "please use `scope` version instead")]
109pub fn yield_from<A: Any, T: Any>(mut g: Generator<A, T>) -> Option<A> {
110 let env = ContextStack::current();
111 let context = env.top();
112 let mut p = context.get_para();
113 while unlikely(!g.is_done()) {
114 match g.raw_send(p) {
115 None => return None,
116 Some(r) => raw_yield(&env, context, r),
117 }
118 p = context.get_para();
119 }
120 drop(g); p
122}
123
124pub fn co_yield_with<T: Any>(v: T) {
126 let env = ContextStack::current();
127 let context = env.co_ctx().unwrap();
128
129 if unlikely(context._ref != 1) {
138 std::panic::panic_any(Error::Cancel);
139 }
140
141 context.co_set_ret(v);
142 context._ref -= 1;
143
144 let parent = env.pop_context(context);
145 let top = unsafe { &mut *context.parent };
146 RegContext::swap(&mut top.regs, &parent.regs);
148}
149
150pub fn co_get_yield<A: Any>() -> Option<A> {
152 ContextStack::current()
153 .co_ctx()
154 .and_then(|ctx| ctx.co_get_para())
155}
156
157pub fn co_set_para<A: Any>(para: A) {
159 if let Some(ctx) = ContextStack::current().co_ctx() {
160 ctx.co_set_para(para)
161 }
162}