--- IO-AIO/AIO.xs 2008/05/11 19:11:05 1.119 +++ IO-AIO/AIO.xs 2008/10/13 10:38:17 1.132 @@ -67,6 +67,12 @@ #endif +/* perl stupidly overrides readdir and maybe others */ +/* with thread-unsafe versions, imagine that :( */ +#undef readdir +#undef opendir +#undef closedir + #define EIO_STRUCT_STAT Stat_t /* use NV for 32 bit perls as it allows larger offsets */ @@ -76,24 +82,37 @@ # define SvVAL64 SvNV #endif +/*****************************************************************************/ + +#if __GNUC__ >= 3 +# define expect(expr,value) __builtin_expect ((expr),(value)) +#else +# define expect(expr,value) (expr) +#endif + +#define expect_false(expr) expect ((expr) != 0, 0) +#define expect_true(expr) expect ((expr) != 0, 1) + +/*****************************************************************************/ + static HV *stash; typedef SV SV8; /* byte-sv, used for argument-checking */ #define AIO_REQ_KLASS "IO::AIO::REQ" #define AIO_GRP_KLASS "IO::AIO::GRP" -#define EIO_COMMON \ +#define EIO_REQ_MEMBERS \ SV *callback; \ SV *sv1, *sv2; \ STRLEN stroffset; \ - SV *self + SV *self; + +#define EIO_NO_WRAPPERS 1 #include "libeio/eio.h" static int req_invoke (eio_req *req); #define EIO_FINISH(req) req_invoke (req) -static void aio_grp_feed (eio_req *grp); -#define EIO_FEED(req) aio_grp_feed (req) static void req_destroy (eio_req *grp); #define EIO_DESTROY(req) req_destroy (req) @@ -107,7 +126,7 @@ typedef eio_req *aio_req_ornot; static SV *on_next_submit; -static int next_pri = EIO_DEFAULT_PRI + EIO_PRI_BIAS; +static int next_pri = EIO_PRI_DEFAULT; static int max_outstanding; static int respipe_osf [2], respipe [2] = { -1, -1 }; @@ -175,7 +194,7 @@ { eio_submit (req); - if (on_next_submit) + if (expect_false (on_next_submit)) { dSP; SV *cb = sv_2mortal (on_next_submit); @@ -195,7 +214,7 @@ if (req->flags & FLAG_SV2_RO_OFF) SvREADONLY_off (req->sv2); - if (!EIO_CANCELLED (req) && SvOK (req->callback)) + if (!EIO_CANCELLED (req) && req->callback) { ENTER; SAVETMPS; @@ -412,7 +431,7 @@ if (size) return; - maybe_start_thread (); + etp_maybe_start_thread (); FD_ZERO (&rfd); FD_SET (respipe [0], &rfd); @@ -423,18 +442,18 @@ static int poll_cb (void) { - int res; - - do + for (;;) { - res = eio_poll (); + int res = eio_poll (); if (res > 0) croak (0); - } - while (max_outstanding && max_outstanding <= eio_nreqs ()); - return res; + if (!max_outstanding || max_outstanding > eio_nreqs ()) + return res; + + poll_wait (); + } } static void atfork_child (void) @@ -442,23 +461,43 @@ create_respipe (); } +static SV * +get_cb (SV *cb_sv) +{ + HV *st; + GV *gvp; + CV *cv; + + if (!SvOK (cb_sv)) + return 0; + + cv = sv_2cv (cb_sv, &st, &gvp, 0); + + if (!cv) + croak ("IO::AIO callback must be undef or a CODE reference"); + + return (SV *)cv; +} + #define dREQ \ + SV *cb_cv; \ aio_req req; \ int req_pri = next_pri; \ - next_pri = EIO_DEFAULT_PRI + EIO_PRI_BIAS; \ + next_pri = EIO_PRI_DEFAULT; \ \ - if (SvOK (callback) && !SvROK (callback)) \ - croak ("callback must be undef or of reference type"); \ + cb_cv = get_cb (callback); \ \ Newz (0, req, 1, eio_req); \ if (!req) \ croak ("out of memory during eio_req allocation"); \ \ - req->callback = newSVsv (callback); \ + req->callback = SvREFCNT_inc (cb_cv); \ req->pri = req_pri #define REQ_SEND \ + PUTBACK; \ req_submit (req); \ + SPAGAIN; \ \ if (GIMME_V != G_VOID) \ XPUSHs (req_sv (req, AIO_REQ_KLASS)); @@ -476,16 +515,7 @@ newCONSTSUB (stash, "O_WRONLY", newSViv (O_WRONLY)); newCONSTSUB (stash, "O_CREAT", newSViv (O_CREAT)); newCONSTSUB (stash, "O_TRUNC", newSViv (O_TRUNC)); -#ifdef _WIN32 - X_MUTEX_CHECK (wrklock); - X_MUTEX_CHECK (reslock); - X_MUTEX_CHECK (reqlock); - X_MUTEX_CHECK (reqwait); - X_MUTEX_CHECK (preadwritelock); - X_MUTEX_CHECK (readdirlock); - - X_COND_CHECK (reqwait); -#else +#ifndef _WIN32 newCONSTSUB (stash, "S_IFIFO", newSViv (S_IFIFO)); #endif @@ -789,13 +819,13 @@ if (SvPOK (req->sv1)) { - req->type = EIO_FCHMOD; - req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); + req->type = ix; + req->ptr1 = SvPVbyte_nolen (req->sv1); } else { - req->type = ix; - req->ptr1 = SvPVbyte_nolen (req->sv1); + req->type = EIO_FCHMOD; + req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); } REQ_SEND; @@ -897,7 +927,7 @@ req->type = EIO_GROUP; - eio_submit (req); + req_submit (req); XPUSHs (req_sv (req, AIO_GRP_KLASS)); } @@ -919,12 +949,12 @@ aioreq_pri (int pri = 0) PROTOTYPE: ;$ CODE: - RETVAL = next_pri - EIO_PRI_BIAS; + RETVAL = next_pri; if (items > 0) { if (pri < EIO_PRI_MIN) pri = EIO_PRI_MIN; if (pri > EIO_PRI_MAX) pri = EIO_PRI_MAX; - next_pri = pri + EIO_PRI_BIAS; + next_pri = pri; } OUTPUT: RETVAL @@ -935,7 +965,7 @@ nice = next_pri - nice; if (nice < EIO_PRI_MIN) nice = EIO_PRI_MIN; if (nice > EIO_PRI_MAX) nice = EIO_PRI_MAX; - next_pri = nice + EIO_PRI_BIAS; + next_pri = nice; void flush () @@ -1006,9 +1036,7 @@ nthreads() PROTOTYPE: CODE: - if (WORDACCESS_UNSAFE) X_LOCK (wrklock); - RETVAL = started; - if (WORDACCESS_UNSAFE) X_UNLOCK (wrklock); + RETVAL = eio_nthreads (); OUTPUT: RETVAL @@ -1028,9 +1056,19 @@ void cb (aio_req_ornot req, SV *callback=&PL_sv_undef) - CODE: - SvREFCNT_dec (req->callback); - req->callback = newSVsv (callback); + PPCODE: +{ + if (GIMME_V != G_VOID) + XPUSHs (req->callback ? sv_2mortal (newRV_inc (req->callback)) : &PL_sv_undef); + + if (items > 1) + { + SV *cb_cv = get_cb (callback); + + SvREFCNT_dec (req->callback); + req->callback = SvREFCNT_inc (cb_cv); + } +} MODULE = IO::AIO PACKAGE = IO::AIO::GRP @@ -1095,7 +1133,8 @@ CODE: { SvREFCNT_dec (grp->sv2); - grp->sv2 = newSVsv (callback); + grp->sv2 = newSVsv (callback); + grp->feed = aio_grp_feed; if (grp->int2 <= 0) grp->int2 = 2;