… | |
… | |
1987 | } |
1987 | } |
1988 | |
1988 | |
1989 | /*****************************************************************************/ |
1989 | /*****************************************************************************/ |
1990 | |
1990 | |
1991 | static void |
1991 | static void |
1992 | coro_semaphore_adjust (pTHX_ AV *av, int adjust) |
1992 | coro_semaphore_adjust (pTHX_ AV *av, IV adjust) |
1993 | { |
1993 | { |
1994 | SV *count_sv = AvARRAY (av)[0]; |
1994 | SV *count_sv = AvARRAY (av)[0]; |
1995 | IV count = SvIVX (count_sv); |
1995 | IV count = SvIVX (count_sv); |
1996 | |
1996 | |
1997 | count += adjust; |
1997 | count += adjust; |
1998 | SvIVX (count_sv) = count; |
1998 | SvIVX (count_sv) = count; |
1999 | |
1999 | |
2000 | /* now wake up as many waiters as possible */ |
2000 | /* now wake up as many waiters as are expected to lock */ |
2001 | while (count > 0 && AvFILLp (av) >= count) |
2001 | while (count > 0 && AvFILLp (av) > 0) |
2002 | { |
2002 | { |
2003 | SV *cb; |
2003 | SV *cb; |
2004 | |
2004 | |
2005 | /* swap first two elements so we can shift a waiter */ |
2005 | /* swap first two elements so we can shift a waiter */ |
2006 | AvARRAY (av)[0] = AvARRAY (av)[1]; |
2006 | AvARRAY (av)[0] = AvARRAY (av)[1]; |
… | |
… | |
2019 | } |
2019 | } |
2020 | |
2020 | |
2021 | static void |
2021 | static void |
2022 | coro_semaphore_on_destroy (pTHX_ struct coro *coro) |
2022 | coro_semaphore_on_destroy (pTHX_ struct coro *coro) |
2023 | { |
2023 | { |
2024 | /* call $sem->adjust (0) to possibly wake up some waiters */ |
2024 | /* call $sem->adjust (0) to possibly wake up some other waiters */ |
2025 | coro_semaphore_adjust (aTHX_ (AV *)coro->slf_frame.data, 0); |
2025 | coro_semaphore_adjust (aTHX_ (AV *)coro->slf_frame.data, 0); |
2026 | } |
2026 | } |
2027 | |
2027 | |
2028 | static int |
2028 | static int |
2029 | slf_check_semaphore_down (pTHX_ struct CoroSLF *frame) |
2029 | slf_check_semaphore_down (pTHX_ struct CoroSLF *frame) |
… | |
… | |
2060 | |
2060 | |
2061 | if (SvIVX (AvARRAY (av)[0]) > 0) |
2061 | if (SvIVX (AvARRAY (av)[0]) > 0) |
2062 | { |
2062 | { |
2063 | frame->data = (void *)av; |
2063 | frame->data = (void *)av; |
2064 | frame->prepare = prepare_nop; |
2064 | frame->prepare = prepare_nop; |
|
|
2065 | SvSTATE_current->on_destroy = coro_semaphore_on_destroy; |
2065 | } |
2066 | } |
2066 | else |
2067 | else |
2067 | { |
2068 | { |
2068 | av_push (av, SvREFCNT_inc (SvRV (coro_current))); |
2069 | av_push (av, SvREFCNT_inc (SvRV (coro_current))); |
2069 | |
2070 | |
2070 | frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av)); |
2071 | frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av)); |
2071 | frame->prepare = prepare_schedule; |
2072 | frame->prepare = prepare_schedule; |
2072 | |
2073 | |
2073 | /* to avoid race conditions when a woken-up coro gets terminated */ |
2074 | /* to avoid race conditions when a woken-up coro gets terminated */ |
2074 | /* we arrange for a temporary on_destroy that calls adjust (0) */ |
2075 | /* we arrange for a temporary on_destroy that calls adjust (0) */ |
|
|
2076 | assert (!SvSTATE_current->on_destroy);//D |
2075 | SvSTATE_current->on_destroy = coro_semaphore_on_destroy; |
2077 | SvSTATE_current->on_destroy = coro_semaphore_on_destroy; |
2076 | } |
2078 | } |
2077 | |
2079 | |
2078 | frame->check = slf_check_semaphore_down; |
2080 | frame->check = slf_check_semaphore_down; |
2079 | |
2081 | |