… | |
… | |
175 | static HV *coro_state_stash, *coro_stash; |
175 | static HV *coro_state_stash, *coro_stash; |
176 | static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */ |
176 | static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */ |
177 | |
177 | |
178 | static AV *av_destroy; /* destruction queue */ |
178 | static AV *av_destroy; /* destruction queue */ |
179 | static SV *sv_manager; /* the manager coro */ |
179 | static SV *sv_manager; /* the manager coro */ |
|
|
180 | static SV *sv_idle; /* $Coro::idle */ |
180 | |
181 | |
181 | static GV *irsgv; /* $/ */ |
182 | static GV *irsgv; /* $/ */ |
182 | static GV *stdoutgv; /* *STDOUT */ |
183 | static GV *stdoutgv; /* *STDOUT */ |
183 | static SV *rv_diehook; |
184 | static SV *rv_diehook; |
184 | static SV *rv_warnhook; |
185 | static SV *rv_warnhook; |
… | |
… | |
1329 | /* TODO: throwing up here is considered harmful */ |
1330 | /* TODO: throwing up here is considered harmful */ |
1330 | |
1331 | |
1331 | if (expect_true (prev != next)) |
1332 | if (expect_true (prev != next)) |
1332 | { |
1333 | { |
1333 | if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW)))) |
1334 | if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW)))) |
1334 | croak ("Coro::State::transfer called with non-running/new prev Coro::State, but can only transfer from running or new states,"); |
1335 | croak ("Coro::State::transfer called with a suspended prev Coro::State, but can only transfer from running or new states,"); |
1335 | |
1336 | |
1336 | if (expect_false (next->flags & CF_RUNNING)) |
1337 | if (expect_false (next->flags & CF_RUNNING)) |
1337 | croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states,"); |
1338 | croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states,"); |
1338 | |
1339 | |
1339 | if (expect_false (next->flags & CF_DESTROYED)) |
1340 | if (expect_false (next->flags & CF_DESTROYED)) |
… | |
… | |
1383 | coro_setup (aTHX_ next); |
1384 | coro_setup (aTHX_ next); |
1384 | } |
1385 | } |
1385 | else |
1386 | else |
1386 | load_perl (aTHX_ next); |
1387 | load_perl (aTHX_ next); |
1387 | |
1388 | |
|
|
1389 | assert (!prev->cctx);//D temporary |
|
|
1390 | |
1388 | /* possibly untie and reuse the cctx */ |
1391 | /* possibly untie and reuse the cctx */ |
1389 | if (expect_true ( |
1392 | if (expect_true ( |
1390 | cctx_current->idle_sp == STACKLEVEL |
1393 | cctx_current->idle_sp == STACKLEVEL |
1391 | && !(cctx_current->flags & CC_TRACE) |
1394 | && !(cctx_current->flags & CC_TRACE) |
1392 | && !force_cctx |
1395 | && !force_cctx |
1393 | )) |
1396 | )) |
1394 | { |
1397 | { |
1395 | /* I assume that stacklevel is a stronger indicator than PL_top_env changes */ |
1398 | /* I assume that stacklevel is a stronger indicator than PL_top_env changes */ |
1396 | assert (("FATAL: current top_env must equal previous top_env in Coro (please report)", PL_top_env == cctx_current->idle_te)); |
1399 | assert (("FATAL: current top_env must equal previous top_env in Coro (please report)", PL_top_env == cctx_current->idle_te)); |
1397 | |
1400 | |
1398 | /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */ |
1401 | /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get. */ |
1399 | /* without this the next cctx_get might destroy the prev__cctx while still in use */ |
1402 | /* without this the next cctx_get might destroy the running cctx while still in use */ |
1400 | if (expect_false (CCTX_EXPIRED (cctx_current))) |
1403 | if (expect_false (CCTX_EXPIRED (cctx_current))) |
1401 | if (!next->cctx) |
1404 | if (expect_true (!next->cctx)) |
1402 | next->cctx = cctx_get (aTHX); |
1405 | next->cctx = cctx_get (aTHX); |
1403 | |
1406 | |
1404 | cctx_put (cctx_current); |
1407 | cctx_put (cctx_current); |
1405 | assert (!prev->cctx);//D temporary |
|
|
1406 | } |
1408 | } |
1407 | else |
1409 | else |
1408 | prev->cctx = cctx_current; |
1410 | prev->cctx = cctx_current; |
1409 | |
1411 | |
1410 | ++next->usecount; |
1412 | ++next->usecount; |
… | |
… | |
1581 | { |
1583 | { |
1582 | struct coro *coro; |
1584 | struct coro *coro; |
1583 | SV *sv_hook; |
1585 | SV *sv_hook; |
1584 | void (*xs_hook)(void); |
1586 | void (*xs_hook)(void); |
1585 | |
1587 | |
1586 | if (SvROK (coro_sv)) |
|
|
1587 | coro_sv = SvRV (coro_sv); |
|
|
1588 | |
|
|
1589 | coro = SvSTATE (coro_sv); |
1588 | coro = SvSTATE (coro_sv); |
1590 | |
1589 | |
1591 | if (coro->flags & CF_READY) |
1590 | if (coro->flags & CF_READY) |
1592 | return 0; |
1591 | return 0; |
1593 | |
1592 | |
… | |
… | |
1667 | } |
1666 | } |
1668 | } |
1667 | } |
1669 | else |
1668 | else |
1670 | { |
1669 | { |
1671 | /* nothing to schedule: call the idle handler */ |
1670 | /* nothing to schedule: call the idle handler */ |
|
|
1671 | if (SvROK (sv_idle) |
|
|
1672 | && SvOBJECT (SvRV (sv_idle))) |
|
|
1673 | { |
|
|
1674 | ++coro_nready; /* hack so that api_ready doesn't invoke ready hook */ |
|
|
1675 | api_ready (SvRV (sv_idle)); |
|
|
1676 | --coro_nready; |
|
|
1677 | } |
|
|
1678 | else |
|
|
1679 | { |
1672 | dSP; |
1680 | dSP; |
1673 | |
1681 | |
1674 | ENTER; |
1682 | ENTER; |
1675 | SAVETMPS; |
1683 | SAVETMPS; |
1676 | |
1684 | |
1677 | PUSHMARK (SP); |
1685 | PUSHMARK (SP); |
1678 | PUTBACK; |
1686 | PUTBACK; |
1679 | call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD); |
1687 | call_sv (sv_idle, G_VOID | G_DISCARD); |
1680 | |
1688 | |
1681 | FREETMPS; |
1689 | FREETMPS; |
1682 | LEAVE; |
1690 | LEAVE; |
|
|
1691 | } |
1683 | } |
1692 | } |
1684 | } |
1693 | } |
1685 | } |
1694 | } |
1686 | |
1695 | |
1687 | INLINE void |
1696 | INLINE void |
… | |
… | |
1758 | static void |
1767 | static void |
1759 | api_trace (pTHX_ SV *coro_sv, int flags) |
1768 | api_trace (pTHX_ SV *coro_sv, int flags) |
1760 | { |
1769 | { |
1761 | struct coro *coro = SvSTATE (coro_sv); |
1770 | struct coro *coro = SvSTATE (coro_sv); |
1762 | |
1771 | |
|
|
1772 | if (coro->flags & CF_RUNNING) |
|
|
1773 | croak ("cannot enable tracing on a running coroutine, caught"); |
|
|
1774 | |
1763 | if (flags & CC_TRACE) |
1775 | if (flags & CC_TRACE) |
1764 | { |
1776 | { |
1765 | if (!coro->cctx) |
1777 | if (!coro->cctx) |
1766 | coro->cctx = cctx_new_run (); |
1778 | coro->cctx = cctx_new_run (); |
1767 | else if (!(coro->cctx->flags & CC_TRACE)) |
1779 | else if (!(coro->cctx->flags & CC_TRACE)) |
1768 | croak ("cannot enable tracing on coroutine with custom stack,"); |
1780 | croak ("cannot enable tracing on coroutine with custom stack, caught"); |
1769 | |
1781 | |
1770 | coro->cctx->flags |= CC_NOREUSE | (flags & (CC_TRACE | CC_TRACE_ALL)); |
1782 | coro->cctx->flags |= CC_NOREUSE | (flags & (CC_TRACE | CC_TRACE_ALL)); |
1771 | } |
1783 | } |
1772 | else if (coro->cctx && coro->cctx->flags & CC_TRACE) |
1784 | else if (coro->cctx && coro->cctx->flags & CC_TRACE) |
1773 | { |
1785 | { |
… | |
… | |
3094 | cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD); |
3106 | cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD); |
3095 | coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current); |
3107 | coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current); |
3096 | av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE); |
3108 | av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE); |
3097 | av_destroy = coro_get_av (aTHX_ "Coro::destroy" , TRUE); |
3109 | av_destroy = coro_get_av (aTHX_ "Coro::destroy" , TRUE); |
3098 | sv_manager = coro_get_sv (aTHX_ "Coro::manager" , TRUE); |
3110 | sv_manager = coro_get_sv (aTHX_ "Coro::manager" , TRUE); |
|
|
3111 | sv_idle = coro_get_sv (aTHX_ "Coro::idle" , TRUE); |
3099 | |
3112 | |
3100 | sv_async_pool_idle = newSVpv ("[async pool idle]", 0); SvREADONLY_on (sv_async_pool_idle); |
3113 | sv_async_pool_idle = newSVpv ("[async pool idle]", 0); SvREADONLY_on (sv_async_pool_idle); |
3101 | sv_Coro = newSVpv ("Coro", 0); SvREADONLY_on (sv_Coro); |
3114 | sv_Coro = newSVpv ("Coro", 0); SvREADONLY_on (sv_Coro); |
3102 | cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler); |
3115 | cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler); |
3103 | cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new); |
3116 | cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new); |