1313namespace Ripple \Runtime ;
1414
1515use Closure ;
16- use Ripple \Runtime \Exception \CoroutineStateException ;
1716use Ripple \Coroutine ;
1817use Ripple \Watch \Interface \WatchAbstract ;
1918use Throwable ;
@@ -37,6 +36,11 @@ final class MainCoroutine extends Coroutine
3736 */
3837 private bool $ hasMessage = false ;
3938
39+ /**
40+ * @var mixed
41+ */
42+ private mixed $ suspendValue = null ;
43+
4044 /**
4145 * 设置主协程为可运行状态
4246 * @return void
@@ -52,6 +56,7 @@ public function runnable(): void
5256 */
5357 public function start (): bool
5458 {
59+ $ this ->setState (Coroutine::STATE_WAITING );
5560 call_user_func ($ this ->callback );
5661 return true ;
5762 }
@@ -64,45 +69,64 @@ public function start(): bool
6469 */
6570 public function suspend (mixed $ value = null ): mixed
6671 {
67- if ($ this ->state === Coroutine::STATE_CREATED ) {
68- Scheduler::start ($ this );
69- return $ this ->result ;
70- }
72+ $ this ->suspendValue = $ value ;
73+ try {
74+ if ($ this ->state === Coroutine::STATE_CREATED ) {
75+ Scheduler::start ($ this );
76+ } else {
77+ $ this ->setState (Coroutine::STATE_WAITING );
78+ Scheduler::tick ();
79+ }
7180
72- if ($ this ->state === Coroutine::STATE_RUNNABLE ) {
73- Scheduler::tick ();
74- return $ this ->result ;
75- }
81+ // 结果暂存
82+ $ result = $ this ->result ;
7683
77- if ($ this ->state === Coroutine::STATE_RUNNING ) {
78- Scheduler::tick ();
79- return $ this ->result ;
84+ // 置空结果
85+ $ this ->result = null ;
86+ $ this ->suspendValue = null ;
87+ return $ result ;
88+ } finally {
89+ $ this ->setState (Coroutine::STATE_RUNNING );
8090 }
81-
82- throw new CoroutineStateException ('Cannot suspend a main coroutine in the current state. ' );
8391 }
8492
8593 /**
8694 * 恢复主协程执行
8795 * @param ?mixed $value 恢复时传入的值
8896 * @return bool 恢复是否成功
97+ * @throws Throwable
8998 */
90- public function resume (mixed $ value = null ): bool
99+ public function resume (mixed $ value = null ): mixed
91100 {
92101 $ this ->hasMessage = true ;
93102 $ this ->result = $ value ;
103+
104+ $ owner = \Co \current ();
105+ if ($ owner instanceof FiberCoroutine) {
106+ Scheduler::nextTick (fn () => Scheduler::resume ($ owner , $ this ->suspendValue ));
107+ return $ owner ->suspend ();
108+ }
109+
94110 return true ;
95111 }
96112
97113 /**
98114 * 向主协程抛出异常
99115 * @param Throwable $exception 要抛出的异常对象
100116 * @return bool 异常设置是否成功
117+ * @throws Throwable
101118 */
102- public function throw (Throwable $ exception ): bool
119+ public function throw (Throwable $ exception ): mixed
103120 {
104121 $ this ->hasMessage = true ;
105122 $ this ->hasExcept = $ exception ;
123+
124+ $ owner = \Co \current ();
125+ if ($ owner instanceof FiberCoroutine) {
126+ Scheduler::nextTick (fn () => Scheduler::resume ($ owner , $ this ->suspendValue ));
127+ return $ owner ->suspend ();
128+ }
129+
106130 return true ;
107131 }
108132
0 commit comments