Exemplo n.º 1
0
/*
 * Arguments: evq_udata, ev_ludata, [callback (function)]
 * Returns: evq_udata | callback (function)
 */
static int
levq_callback (lua_State *L)
{
    struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME);
    struct event *ev = levq_toevent(L, 2);
    lua_State *NL = evq->L;
    const int top = lua_gettop(L);

    lua_assert(ev && !event_deleted(ev));

    if (top < 3) {
	lua_rawgeti(NL, EVQ_CORO_CALLBACK, ev->ev_id);
	lua_xmove(NL, L, 1);
    } else {
	ev->flags &= ~(EVENT_CALLBACK | EVENT_CALLBACK_CORO);
	if (!lua_isnoneornil(L, 3)) {
	    ev->flags |= EVENT_CALLBACK
	     | (lua_isthread(L, 3) ? EVENT_CALLBACK_CORO : 0);
	}

	lua_settop(L, 3);
	lua_xmove(L, NL, 1);
	lua_rawseti(NL, EVQ_CORO_CALLBACK, ev->ev_id);
	lua_settop(L, 1);
    }
    return 1;
}
Exemplo n.º 2
0
/*
 * Arguments: evq_udata, ev_ludata, [reuse_fd (boolean)]
 * Returns: [evq_udata]
 */
static int
levq_del (lua_State *L)
{
    struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME);
    struct event *ev = levq_toevent(L, 2);
    const int reuse_fd = lua_toboolean(L, 3);
    int res = 0;

    lua_assert(ev);

#undef ARG_LAST
#define ARG_LAST	1

#ifdef EVQ_POST_INIT
    if (ev == evq->ev_post)
	evq->ev_post = NULL;
#endif

    if (!event_deleted(ev))
	res = evq_del(ev, reuse_fd);

    if (!(ev->flags & (EVENT_ACTIVE | EVENT_DELETE)))
	levq_del_event(evq, ev);

    ev->flags |= EVENT_DELETE;

    if (!res) {
	lua_settop(L, 1);
	return 1;
    }
    return sys_seterror(L, 0);
}
Exemplo n.º 3
0
/*
 * Arguments: evq_udata, ev_ludata, [manually/auto-reset (boolean)]
 * Returns: [evq_udata]
 */
static int
levq_timeout_manual (lua_State *L)
{
    struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME);
    struct event *ev = levq_toevent(L, 2);
    const int manual = lua_toboolean(L, 3);

    (void) evq;

    lua_assert(ev && !event_deleted(ev) && !(ev->flags & EVENT_WINMSG));

    if (manual)
	ev->flags |= EVENT_TIMEOUT_MANUAL;
    else
	ev->flags &= ~EVENT_TIMEOUT_MANUAL;

    lua_settop(L, 1);
    return 1;
}
Exemplo n.º 4
0
/*
 * Arguments: evq_udata, ev_ludata, events (string: "r", "w")
 * Returns: [evq_udata]
 */
static int
levq_mod_socket (lua_State *L)
{
    struct event *ev = levq_toevent(L, 2);
    const char *evstr = luaL_checkstring(L, 3);
    const unsigned int rw_flags = (evstr[0] == 'r')
     ? EVENT_READ : EVENT_WRITE;

    lua_assert(ev && !event_deleted(ev) && (ev->flags & EVENT_SOCKET)
     && rw_flags != (ev->flags & (EVENT_READ | EVENT_WRITE)));

    if (!evq_modify(ev, rw_flags)) {
	ev->flags &= ~(EVENT_READ | EVENT_WRITE);
	ev->flags |= rw_flags;
	lua_settop(L, 1);
	return 1;
    }
    return sys_seterror(L, 0);
}
Exemplo n.º 5
0
/*
 * Arguments: evq_udata, ev_ludata, [timeout (milliseconds)]
 * Returns: [evq_udata]
 */
static int
levq_timeout (lua_State *L)
{
    struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME);
    struct event *ev = levq_toevent(L, 2);
    const msec_t timeout = lua_isnoneornil(L, 3)
     ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 3);

    lua_assert(ev && !event_deleted(ev) && !(ev->flags & EVENT_WINMSG));

    /* reserve place for timeout_queue */
    if (!evq->ev_free)
	evq->ev_free = levq_new_event(evq);

    if (!evq_set_timeout(ev, timeout)) {
	lua_settop(L, 1);
	return 1;
    }
    return sys_seterror(L, 0);
}
Exemplo n.º 6
0
/*
 * Arguments: evq_udata
 */
static int
levq_done (lua_State *L)
{
    struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME);
    struct event *buffers[EVQ_ENV_BUF_MAX + 1];  /* cache */
    lua_State *NL = evq->L;

    memset(buffers, 0, sizeof(buffers));

#undef ARG_LAST
#define ARG_LAST	1

    /* delete object events */
    lua_pushnil(NL);
    while (lua_next(NL, EVQ_CORO_UDATA)) {
	const int ev_id = lua_tointeger(NL, -2);
	const int buf_idx = getmaxbit(
	 (ev_id | ((1 << EVQ_ENV_BUF_IDX) - 1)) + 1);
	const int nmax = (1 << buf_idx);
	struct event *ev = buffers[buf_idx];

	if (!ev) {
	    lua_rawgeti(NL, EVQ_CORO_ENV, buf_idx - EVQ_ENV_BUF_IDX + 1);
	    ev = lua_touserdata(NL, -1);
	    lua_pop(NL, 1);  /* pop events buffer */
	    buffers[buf_idx] = ev;
	}
	ev += ev_id - ((nmax - 1) & ~((1 << EVQ_ENV_BUF_IDX) - 1));

	if (!event_deleted(ev))
	    evq_del(ev, 0);
	lua_pop(NL, 1);  /* pop value */
    }

    evq_done(evq);
    return 0;
}
Exemplo n.º 7
0
static void
signal_handler (const int signo)
{
#ifdef USE_KQUEUE
  (void) signo;
#else
  struct event **sig_evp;

  if (signo == SYS_SIGINTR) return;

  sig_evp = signal_gethead(signo);
  if (!sig_evp) return;

  pthread_mutex_lock(&g_Signal.cs);
  {
    struct event *ev = *sig_evp;
    for (; ev; ev = ev->next_object) {
      if (!event_deleted(ev))
        evq_signal(ev->evq, signo);
    }
  }
  pthread_mutex_unlock(&g_Signal.cs);
#endif
}
Exemplo n.º 8
0
/*
 * Arguments: evq_udata, [timeout (milliseconds), once (boolean),
 *	fetch (boolean)]
 * Returns: [evq_udata | timeout (false)]
 *	|
 * Returns: [ev_ludata, obj_udata, event (string: "r", "w", "t", "e"),
 *	eof_status (number)]
 */
static int
levq_loop (lua_State *L)
{
    struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME);
    const msec_t timeout = (lua_type(L, 2) != LUA_TNUMBER)
     ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 2);
    const int once = lua_toboolean(L, 3);
    const int fetch = lua_toboolean(L, 4);

#undef ARG_LAST
#define ARG_LAST	1

    lua_settop(L, ARG_LAST);
    {
	lua_State *NL = evq->L;

	lua_pushvalue(NL, EVQ_CORO_CALLBACK);
	lua_pushvalue(NL, EVQ_CORO_UDATA);
	lua_xmove(NL, L, 2);
    }

#ifdef EVQ_POST_INIT
    if (evq->ev_post) {
	evq_post_init(evq->ev_post);
	evq->ev_post = NULL;
    }
#endif

    while (!evq_is_empty(evq)) {
	struct event *ev;

	if (evq->stop) {
	    evq->stop = 0;
	    break;
	}

	/* process synchronous operations */
	if (evq->sync_op) {
	    struct evq_sync_op *op = evq->sync_op;

	    evq->sync_op = NULL;
	    levq_sync_process(L, evq, op);
	}

	if (!evq->ev_ready) {
	    const int res = evq_wait(evq, timeout);

	    if (res == EVQ_TIMEOUT) {
		lua_pushboolean(L, 0);
		return 1;
	    }
	    if (res == EVQ_FAILED)
		return sys_seterror(L, 0);
	}

	ev = evq->ev_ready;
	if (!ev) continue;
	do {
	    const unsigned int ev_flags = ev->flags;

	    /* clear EVENT_ACTIVE and EVENT_*_RES flags */
	    ev->flags &= EVENT_MASK;
	    evq->ev_ready = ev->next_ready;

	    if (ev_flags & EVENT_DELETE) {
		/* postponed deletion of active event */
		levq_del_event(evq, ev);
	    } else {
		if ((ev_flags & EVENT_CALLBACK) || fetch) {
		    const int ev_id = ev->ev_id;

		    /* callback function */
		    lua_rawgeti(L, ARG_LAST+1, ev_id);
		    /* arguments */
		    if (!(ev_flags & EVENT_CALLBACK_SCHED)) {
			lua_pushvalue(L, 1);  /* evq_udata */
			lua_pushlightuserdata(L, ev);  /* ev_ludata */
			lua_rawgeti(L, ARG_LAST+2, ev_id);  /* obj_udata */
		    }
		    if (ev_flags & EVENT_EOF_MASK_RES) {
			lua_pushliteral(L, "e");
			lua_pushinteger(L,
			 (int) ev_flags >> EVENT_EOF_SHIFT_RES);
		    } else {
			lua_pushstring(L,
			 (ev_flags & EVENT_TIMEOUT_RES) ? "t"
			 : (ev_flags & EVENT_WRITE_RES) ? "w" : "r");
			lua_pushnil(L);
		    }
		}

		if ((ev_flags & EVENT_ONESHOT) && !event_deleted(ev))
		    evq_del(ev, 1);

		if (event_deleted(ev))
		    levq_del_event(evq, ev);  /* deletion of oneshot event */
#ifdef EVQ_POST_INIT
		else evq->ev_post = ev;
#endif

		if (ev_flags & EVENT_CALLBACK_SCHED) {
		    /* callback function: coroutine */
		    lua_State *co = lua_tothread(L, ARG_LAST+3);

		    lua_xmove(L, co, 2);
		    lua_pop(L, 1);  /* pop coroutine */

		    sys_sched_event_ready(co, ev);
		} else if (ev_flags & EVENT_CALLBACK_CORO) {
		    lua_State *co = lua_tothread(L, ARG_LAST+3);

		    lua_xmove(L, co, 5);
		    lua_pop(L, 1);  /* pop coroutine */

		    switch (lua_resume(co, L, 5)) {
		    case 0:
			lua_settop(co, 0);
			if (!event_deleted(ev)) {
			    evq_del(ev, 0);
			    levq_del_event(evq, ev);
#ifdef EVQ_POST_INIT
			    evq->ev_post = NULL;
#endif
			}
			break;
		    case LUA_YIELD:
			lua_settop(co, 0);
			break;
		    default:
			lua_xmove(co, L, 1);  /* error message */
			lua_error(L);
		    }
		} else if (ev_flags & EVENT_CALLBACK)
		    lua_call(L, 5, 0);
		else if (fetch)
		    return 4;

#ifdef EVQ_POST_INIT
		if (evq->ev_post) {
		    evq_post_init(evq->ev_post);
		    evq->ev_post = NULL;
		}
#endif
	    }
	    ev = evq->ev_ready;
	} while (ev);