ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
(Generate patch)

Comparing Coro/Coro/State.xs (file contents):
Revision 1.299 by root, Wed Nov 19 00:06:55 2008 UTC vs.
Revision 1.300 by root, Wed Nov 19 02:07:48 2008 UTC

1995 PerlIOBuf_get_cnt, 1995 PerlIOBuf_get_cnt,
1996 PerlIOBuf_set_ptrcnt, 1996 PerlIOBuf_set_ptrcnt,
1997}; 1997};
1998 1998
1999/*****************************************************************************/ 1999/*****************************************************************************/
2000/* Coro::Semaphore */ 2000/* Coro::Semaphore & Coro::Signal */
2001 2001
2002static SV * 2002static SV *
2003coro_semaphore_new (int count) 2003coro_waitarray_new (pTHX_ int count)
2004{ 2004{
2005 /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */ 2005 /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */
2006 AV *av = newAV (); 2006 AV *av = newAV ();
2007 SV **ary; 2007 SV **ary;
2008 2008
2015 ary [0] = newSViv (count); 2015 ary [0] = newSViv (count);
2016 2016
2017 return newRV_noinc ((SV *)av); 2017 return newRV_noinc ((SV *)av);
2018} 2018}
2019 2019
2020/* semaphore */
2021
2020static void 2022static void
2021coro_semaphore_adjust (pTHX_ AV *av, IV adjust) 2023coro_semaphore_adjust (pTHX_ AV *av, IV adjust)
2022{ 2024{
2023 SV *count_sv = AvARRAY (av)[0]; 2025 SV *count_sv = AvARRAY (av)[0];
2024 IV count = SvIVX (count_sv); 2026 IV count = SvIVX (count_sv);
2135static void 2137static void
2136slf_init_semaphore_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2138slf_init_semaphore_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2137{ 2139{
2138 slf_init_semaphore_down_or_wait (aTHX_ frame, cv, arg, items); 2140 slf_init_semaphore_down_or_wait (aTHX_ frame, cv, arg, items);
2139 frame->check = slf_check_semaphore_wait; 2141 frame->check = slf_check_semaphore_wait;
2142}
2143
2144/* signal */
2145
2146static void
2147coro_signal_wake (pTHX_ AV *av, int count)
2148{
2149 SvIVX (AvARRAY (av)[0]) = 0;
2150
2151 /* now signal count waiters */
2152 while (count > 0 && AvFILLp (av) > 0)
2153 {
2154 SV *cb;
2155
2156 /* swap first two elements so we can shift a waiter */
2157 cb = AvARRAY (av)[0];
2158 AvARRAY (av)[0] = AvARRAY (av)[1];
2159 AvARRAY (av)[1] = cb;
2160
2161 cb = av_shift (av);
2162
2163 api_ready (cb);
2164 sv_setiv (cb, 0); /* signal waiter */
2165 SvREFCNT_dec (cb);
2166
2167 --count;
2168 }
2169}
2170
2171static int
2172slf_check_signal_wait (pTHX_ struct CoroSLF *frame)
2173{
2174 /* if we are about to throw, also stop waiting */
2175 return SvROK ((SV *)frame->data) && !CORO_THROW;
2176}
2177
2178static void
2179slf_init_signal_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2180{
2181 AV *av = (AV *)SvRV (arg [0]);
2182
2183 if (SvIVX (AvARRAY (av)[0]))
2184 {
2185 SvIVX (AvARRAY (av)[0]) = 0;
2186 frame->prepare = prepare_nop;
2187 frame->check = slf_check_nop;
2188 }
2189 else
2190 {
2191 SV *waiter = newRV_inc (SvRV (coro_current)); /* owned by signal av */
2192
2193 av_push (av, waiter);
2194
2195 frame->data = (void *)sv_2mortal (SvREFCNT_inc_NN (waiter)); /* owned by process */
2196 frame->prepare = prepare_schedule;
2197 frame->check = slf_check_signal_wait;
2198 }
2140} 2199}
2141 2200
2142/*****************************************************************************/ 2201/*****************************************************************************/
2143/* gensub: simple closure generation utility */ 2202/* gensub: simple closure generation utility */
2144 2203
2821 2880
2822SV * 2881SV *
2823new (SV *klass, SV *count = 0) 2882new (SV *klass, SV *count = 0)
2824 CODE: 2883 CODE:
2825 RETVAL = sv_bless ( 2884 RETVAL = sv_bless (
2826 coro_semaphore_new (count && SvOK (count) ? SvIV (count) : 1), 2885 coro_waitarray_new (aTHX_ count && SvOK (count) ? SvIV (count) : 1),
2827 GvSTASH (CvGV (cv)) 2886 GvSTASH (CvGV (cv))
2828 ); 2887 );
2829 OUTPUT: 2888 OUTPUT:
2830 RETVAL 2889 RETVAL
2831 2890
2832# helper for Coro::Channel 2891# helper for Coro::Channel
2833SV * 2892SV *
2834_alloc (int count) 2893_alloc (int count)
2835 CODE: 2894 CODE:
2836 RETVAL = coro_semaphore_new (count); 2895 RETVAL = coro_waitarray_new (aTHX_ count);
2837 OUTPUT: 2896 OUTPUT:
2838 RETVAL 2897 RETVAL
2839 2898
2840SV * 2899SV *
2841count (SV *self) 2900count (SV *self)
2851 CODE: 2910 CODE:
2852 coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1); 2911 coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1);
2853 2912
2854void 2913void
2855down (SV *self) 2914down (SV *self)
2856 ALIAS:
2857 Coro::Signal::wait = 0
2858 CODE: 2915 CODE:
2859 CORO_EXECUTE_SLF_XS (slf_init_semaphore_down); 2916 CORO_EXECUTE_SLF_XS (slf_init_semaphore_down);
2860 2917
2861void 2918void
2862wait (SV *self) 2919wait (SV *self)
2903 2960
2904SV * 2961SV *
2905new (SV *klass) 2962new (SV *klass)
2906 CODE: 2963 CODE:
2907 RETVAL = sv_bless ( 2964 RETVAL = sv_bless (
2908 coro_semaphore_new (0), 2965 coro_waitarray_new (aTHX_ 0),
2909 GvSTASH (CvGV (cv)) 2966 GvSTASH (CvGV (cv))
2910 ); 2967 );
2911 OUTPUT: 2968 OUTPUT:
2912 RETVAL 2969 RETVAL
2913 2970
2914void 2971void
2915broadcast (SV *self, int adjust = 1) 2972wait (SV *self)
2916 CODE: 2973 CODE:
2974 CORO_EXECUTE_SLF_XS (slf_init_signal_wait);
2975
2976void
2977broadcast (SV *self)
2978 CODE:
2979{
2980 AV *av = (AV *)SvRV (self);
2981 coro_signal_wake (aTHX_ av, AvFILLp (av));
2982}
2983
2984void
2985send (SV *self)
2986 CODE:
2917{ 2987{
2918 AV *av = (AV *)SvRV (self); 2988 AV *av = (AV *)SvRV (self);
2919 SvIVX (AvARRAY (av)[0]) = 0; /* not necessary, but gives me fuzzy warm feelings */ 2989
2920 coro_semaphore_adjust (aTHX_ av, AvFILLp (av) + 1 - 1); 2990 if (AvFILLp (av))
2991 coro_signal_wake (av, 1);
2992 else
2921 SvIVX (AvARRAY (av)[0]) = 0; /* necessary */ 2993 SvIVX (AvARRAY (av)[0]) = 1; /* remember the signal */
2922} 2994}
2995
2996IV
2997awaited (SV *self)
2998 CODE:
2999 RETVAL = AvFILLp ((AV *)SvRV (self)) + 1 - 1;
3000 OUTPUT:
3001 RETVAL
2923 3002
2924 3003
2925MODULE = Coro::State PACKAGE = Coro::AnyEvent 3004MODULE = Coro::State PACKAGE = Coro::AnyEvent
2926 3005
2927BOOT: 3006BOOT:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines