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,60 @@ 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- }
71-
72- if ($ this ->state === Coroutine::STATE_RUNNABLE ) {
73- Scheduler::tick ();
74- return $ this ->result ;
75- }
72+ $ this ->suspendValue = $ value ;
73+ try {
74+ if ($ this ->state === Coroutine::STATE_CREATED ) {
75+ Scheduler::start ($ this );
76+ $ this ->suspendValue = null ;
77+ return $ this ->result ;
78+ }
7679
77- if ( $ this ->state === Coroutine::STATE_RUNNING ) {
80+ $ this ->setState ( Coroutine::STATE_WAITING );
7881 Scheduler::tick ();
82+ $ this ->suspendValue = null ;
7983 return $ this ->result ;
84+ } finally {
85+ $ this ->setState (Coroutine::STATE_RUNNING );
8086 }
81-
82- throw new CoroutineStateException ('Cannot suspend a main coroutine in the current state. ' );
8387 }
8488
8589 /**
8690 * 恢复主协程执行
8791 * @param ?mixed $value 恢复时传入的值
8892 * @return bool 恢复是否成功
93+ * @throws Throwable
8994 */
90- public function resume (mixed $ value = null ): bool
95+ public function resume (mixed $ value = null ): mixed
9196 {
9297 $ this ->hasMessage = true ;
9398 $ this ->result = $ value ;
99+
100+ $ owner = \Co \current ();
101+ if ($ owner instanceof FiberCoroutine) {
102+ Scheduler::nextTick (fn () => Scheduler::resume ($ owner , $ this ->suspendValue ));
103+ return $ owner ->suspend ();
104+ }
105+
94106 return true ;
95107 }
96108
97109 /**
98110 * 向主协程抛出异常
99111 * @param Throwable $exception 要抛出的异常对象
100112 * @return bool 异常设置是否成功
113+ * @throws Throwable
101114 */
102- public function throw (Throwable $ exception ): bool
115+ public function throw (Throwable $ exception ): mixed
103116 {
104117 $ this ->hasMessage = true ;
105118 $ this ->hasExcept = $ exception ;
119+
120+ $ owner = \Co \current ();
121+ if ($ owner instanceof FiberCoroutine) {
122+ Scheduler::nextTick (fn () => Scheduler::resume ($ owner , $ this ->suspendValue ));
123+ return $ owner ->suspend ();
124+ }
125+
106126 return true ;
107127 }
108128
0 commit comments