/* * Arguments: dpool_udata, data_items (any) ... */ static int dpool_put (lua_State *L) { struct sys_thread *td = sys_thread_get(); struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); int nput = lua_gettop(L) - 1; if (!td) luaL_argerror(L, 0, "Threading not initialized"); if (!nput) luaL_argerror(L, 2, "data expected"); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); if (dp->n >= dp->max) { if (dp->flags & DPOOL_PUTONFULL) { lua_rawgetp(L, 1, (void *) DPOOL_PUTONFULL); lua_insert(L, 2); lua_call(L, 1 + nput, LUA_MULTRET); nput = lua_gettop(L) - 1; if (!nput) return 0; } else { do { const int res = thread_event_wait(&dp->tev, td, TIMEOUT_INFINITE); sys_thread_check(td); if (res) return sys_seterror(L, 0); } while (dp->n >= dp->max); } } /* Try directly move data between threads */ if (dp->nwaits && !dp->td) { dp->td = td; dp->nput = nput; thread_event_signal(&dp->tev); sys_thread_switch(0); dp->td = NULL; if (!dp->nput) return 0; /* moved to thread */ dp->nput = 0; } /* Keep data in the storage */ { int top = dp->top; lua_pushinteger(L, nput); do { lua_rawseti(L, 1, ++top); } while (nput--); dp->top = top; if (!dp->n++) { thread_event_signal(&dp->tev); } } return 0; }
/* * Arguments: dpool_udata, data_items (any) ... */ static int dpool_put (lua_State *L) { struct sys_thread *td = sys_get_thread(); struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); int nput = lua_gettop(L) - 1; if (!td) luaL_argerror(L, 0, "Threading not initialized"); if (!nput) luaL_argerror(L, 2, "data expected"); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); if (dp->n >= dp->max) { if (dp->flags & DPOOL_PUTONFULL) { lua_pushlightuserdata(L, (void *) DPOOL_PUTONFULL); lua_rawget(L, 1); lua_insert(L, 2); lua_call(L, 1 + nput, LUA_MULTRET); nput = lua_gettop(L) - 1; if (!nput) return 0; } else do { if (thread_event_wait(&dp->tev, TIMEOUT_INFINITE)) return sys_seterror(L, 0); } while (dp->n >= dp->max); } /* Try directly move data between threads */ if (dp->nwaits && !dp->td) { dp->td = td; dp->nput = nput; thread_event_signal(&dp->tev); thread_yield(L); dp->td = NULL; if (!dp->nput) return 0; /* moved to thread */ dp->nput = 0; } /* Keep data in the storage */ { int top = dp->top; lua_pushinteger(L, nput); do { lua_rawseti(L, 1, ++top); } while (nput--); dp->top = top; /* notify event_queue */ if (!dp->n++ && dp->trigger) sys_trigger_notify(&dp->trigger, SYS_EVREAD); thread_event_signal(&dp->tev); } return 0; }
static void func(void * p) { struct args * arg = p; if (arg->wait) { thread_event_wait(arg->wait); } printf("n = %d\n", arg->n); if (arg->trigger) { thread_event_trigger(arg->trigger); } }
/* * Arguments: dpool_udata, [timeout (milliseconds)] * Returns: [signalled/timedout (boolean)] */ static int dpool_wait (lua_State *L) { struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); const msec_t timeout = lua_isnoneornil(L, 2) ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 2); int res; res = thread_event_wait(&dp->tev, timeout); if (res >= 0) { lua_pushboolean(L, !res); return 1; } return sys_seterror(L, 0); }
static void worker_func(void *p) { struct worker *w = p; for (;;) { w->suspend = 0; while (run_slice(w)) { struct workshop * ws = w->workshop; int i; for (i=0;i<ws->threads;i++) { struct worker *w = &ws->w[i]; if (w->suspend) { thread_event_trigger(&w->event); } } } w->suspend = 1; thread_event_wait(&w->event); } }
/* * Arguments: dpool_udata, [timeout (milliseconds)] * Returns: data_items (any) ... */ static int dpool_get (lua_State *L) { struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); const msec_t timeout = lua_isnoneornil(L, 2) ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 2); int nput; lua_settop(L, 1); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); if ((dp->flags & DPOOL_GETONEMPTY) && !dp->n) { lua_pushlightuserdata(L, (void *) DPOOL_GETONEMPTY); lua_rawget(L, 1); lua_insert(L, 2); lua_call(L, 1, LUA_MULTRET); nput = lua_gettop(L) - 1; if (nput) return nput; } for (; ; ) { /* get from storage */ if (dp->n) { const int idx = dp->idx + 1; int i; lua_rawgeti(L, 1, idx); nput = lua_tointeger(L, -1); lua_pushnil(L); lua_rawseti(L, 1, idx); dp->idx = idx + nput; for (i = dp->idx; i > idx; --i) { lua_rawgeti(L, 1, i); lua_pushnil(L); lua_rawseti(L, 1, i); } if (dp->idx == dp->top) dp->idx = dp->top = 0; if (dp->n-- == dp->max) { /* notify event_queue */ if (dp->trigger) sys_trigger_notify(&dp->trigger, SYS_EVWRITE); thread_event_signal(&dp->tev); } return nput; } /* wait signal */ { int res; dp->nwaits++; res = thread_event_wait(&dp->tev, timeout); dp->nwaits--; if (res) { if (res == 1) { lua_pushboolean(L, 0); return 1; /* timed out */ } return sys_seterror(L, 0); } } /* get directly from another thread */ nput = dp->nput; if (nput) { dp->nput = 0; lua_xmove(dp->td->L, L, nput); return nput; } } }