File tree Expand file tree Collapse file tree 6 files changed +260
-0
lines changed
Expand file tree Collapse file tree 6 files changed +260
-0
lines changed Original file line number Diff line number Diff line change 1+ --TEST--
2+ Cancel fiber's coroutine via getCoroutine()->cancel()
3+ --FILE--
4+ <?php
5+
6+ use function Async \spawn ;
7+ use function Async \await ;
8+ use Async \CancellationError ;
9+
10+ $ c = spawn (function () {
11+ $ fiber = new Fiber (function () {
12+ echo "Fiber started \n" ;
13+ Fiber::suspend ("suspended " );
14+ echo "Fiber resumed \n" ;
15+ return "done " ;
16+ });
17+
18+ $ fiber ->start ();
19+ echo "Fiber suspended \n" ;
20+
21+ // Get fiber's coroutine and cancel it
22+ $ coro = $ fiber ->getCoroutine ();
23+ $ coro ->cancel (new CancellationError ("cancelled " ));
24+ echo "Coroutine cancelled \n" ;
25+
26+ // Try to resume fiber
27+ try {
28+ $ fiber ->resume ();
29+ echo "Fiber completed \n" ;
30+ } catch (CancellationError $ e ) {
31+ echo "CancellationError: " . $ e ->getMessage () . "\n" ;
32+ } catch (FiberError $ e ) {
33+ echo "FiberError: " . $ e ->getMessage () . "\n" ;
34+ }
35+ });
36+
37+ await ($ c );
38+ echo "OK \n" ;
39+ ?>
40+ --EXPECTF--
41+ Fiber started
42+ Fiber suspended
43+ Coroutine cancelled
44+ %a
45+ OK
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Cancel fiber's coroutine while fiber is suspended
3+ --FILE--
4+ <?php
5+
6+ use function Async \spawn ;
7+ use function Async \suspend ;
8+ use function Async \await ;
9+ use Async \CancellationError ;
10+
11+ $ c = spawn (function () {
12+ $ fiber = new Fiber (function () {
13+ echo "Fiber: before suspend \n" ;
14+ Fiber::suspend ();
15+ echo "Fiber: after suspend \n" ;
16+ return "result " ;
17+ });
18+
19+ $ fiber ->start ();
20+
21+ // Fiber is suspended, cancel its coroutine
22+ $ coro = $ fiber ->getCoroutine ();
23+ echo "Cancelling coroutine \n" ;
24+ $ coro ->cancel (new CancellationError ("test " ));
25+
26+ // Give scheduler a chance
27+ suspend ();
28+
29+ // Try resume
30+ try {
31+ $ fiber ->resume ();
32+ } catch (Throwable $ e ) {
33+ echo "Caught: " . $ e ->getMessage () . "\n" ;
34+ }
35+ });
36+
37+ await ($ c );
38+ echo "OK \n" ;
39+ ?>
40+ --EXPECTF--
41+ Fiber: before suspend
42+ Cancelling coroutine
43+ Caught: Cannot resume a fiber that is not suspended
44+ OK
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Double cancel - parent coroutine and fiber's coroutine
3+ --FILE--
4+ <?php
5+
6+ use function Async \spawn ;
7+ use function Async \await ;
8+ use Async \CancellationError ;
9+
10+ $ parent = spawn (function () {
11+ $ fiber = new Fiber (function () {
12+ Fiber::suspend ();
13+ return "done " ;
14+ });
15+
16+ $ fiber ->start ();
17+
18+ // Cancel fiber's coroutine
19+ $ fiberCoro = $ fiber ->getCoroutine ();
20+ $ fiberCoro ->cancel (new CancellationError ("fiber cancel " ));
21+ echo "Fiber coroutine cancelled \n" ;
22+
23+ // Try resume
24+ try {
25+ $ fiber ->resume ();
26+ } catch (Throwable $ e ) {
27+ echo "Fiber caught: " . $ e ->getMessage () . "\n" ;
28+ }
29+
30+ return "parent done " ;
31+ });
32+
33+ // Also cancel parent
34+ $ parent ->cancel (new CancellationError ("parent cancel " ));
35+ echo "Parent cancelled \n" ;
36+
37+ try {
38+ await ($ parent );
39+ } catch (CancellationError $ e ) {
40+ echo "Parent caught: " . $ e ->getMessage () . "\n" ;
41+ }
42+
43+ echo "OK \n" ;
44+ ?>
45+ --EXPECTF--
46+ %a
47+ OK
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Get fiber's coroutine after fiber termination
3+ --FILE--
4+ <?php
5+
6+ use function Async \spawn ;
7+ use function Async \await ;
8+
9+ $ c = spawn (function () {
10+ $ fiber = new Fiber (function () {
11+ return "done " ;
12+ });
13+
14+ $ result = $ fiber ->start ();
15+ echo "Fiber completed: {$ result }\n" ;
16+
17+ // Get coroutine after fiber is terminated
18+ $ coro = $ fiber ->getCoroutine ();
19+
20+ if ($ coro !== null ) {
21+ echo "Has coroutine: yes \n" ;
22+ echo "Is finished: " . ($ coro ->isFinished () ? "yes " : "no " ) . "\n" ;
23+ } else {
24+ echo "Has coroutine: no \n" ;
25+ }
26+
27+ return "ok " ;
28+ });
29+
30+ await ($ c );
31+ echo "OK \n" ;
32+ ?>
33+ --EXPECTF--
34+ Fiber completed: done
35+ Has coroutine: yes
36+ Is finished: yes
37+ OK
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Cancel fiber's coroutine from nested spawn
3+ --FILE--
4+ <?php
5+
6+ use function Async \spawn ;
7+ use function Async \suspend ;
8+ use function Async \await ;
9+ use Async \CancellationError ;
10+
11+ $ outer = spawn (function () {
12+ $ fiber = new Fiber (function () {
13+ echo "Fiber running \n" ;
14+ Fiber::suspend ();
15+ echo "This should not print \n" ;
16+ return "done " ;
17+ });
18+
19+ $ fiber ->start ();
20+ $ fiberCoro = $ fiber ->getCoroutine ();
21+
22+ // Nested coroutine cancels fiber's coroutine
23+ $ inner = spawn (function () use ($ fiberCoro ) {
24+ echo "Inner: cancelling fiber coroutine \n" ;
25+ $ fiberCoro ->cancel (new CancellationError ("nested cancel " ));
26+ });
27+
28+ await ($ inner );
29+ suspend ();
30+
31+ // Try to use fiber
32+ try {
33+ $ fiber ->resume ();
34+ } catch (Throwable $ e ) {
35+ echo "Caught: " . $ e ->getMessage () . "\n" ;
36+ }
37+
38+ return "outer done " ;
39+ });
40+
41+ $ result = await ($ outer );
42+ echo "Result: {$ result }\n" ;
43+ echo "OK \n" ;
44+ ?>
45+ --EXPECTF--
46+ Fiber running
47+ Inner: cancelling fiber coroutine
48+ %a
49+ OK
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Fiber throws exception while coroutine is being cancelled
3+ --FILE--
4+ <?php
5+
6+ use function Async \spawn ;
7+ use function Async \await ;
8+ use Async \CancellationError ;
9+
10+ $ c = spawn (function () {
11+ $ fiber = new Fiber (function () {
12+ Fiber::suspend ();
13+ throw new Exception ("fiber exception " );
14+ });
15+
16+ $ fiber ->start ();
17+ $ coro = $ fiber ->getCoroutine ();
18+
19+ // Cancel coroutine
20+ $ coro ->cancel (new CancellationError ("cancel " ));
21+
22+ // Resume - what happens? Exception or CancellationError?
23+ try {
24+ $ fiber ->resume ();
25+ echo "No exception \n" ;
26+ } catch (CancellationError $ e ) {
27+ echo "CancellationError: " . $ e ->getMessage () . "\n" ;
28+ } catch (Exception $ e ) {
29+ echo "Exception: " . $ e ->getMessage () . "\n" ;
30+ }
31+ });
32+
33+ await ($ c );
34+ echo "OK \n" ;
35+ ?>
36+ --EXPECTF--
37+ %a
38+ OK
You can’t perform that action at this time.
0 commit comments