util-src/poll.c
changeset 12318 898554323338
parent 10925 6eb5d2bb11af
child 12319 cf2086a1bd45
equal deleted inserted replaced
12317:469e4453ed01 12318:898554323338
    10 
    10 
    11 #include <unistd.h>
    11 #include <unistd.h>
    12 #include <string.h>
    12 #include <string.h>
    13 #include <errno.h>
    13 #include <errno.h>
    14 
    14 
    15 #ifdef __linux__
    15 #if defined(__linux__)
    16 #define USE_EPOLL
    16 #define USE_EPOLL
       
    17 #else
       
    18 #define USE_SELECT
    17 #endif
    19 #endif
    18 
    20 
    19 #ifdef USE_EPOLL
    21 #ifdef USE_EPOLL
    20 #include <sys/epoll.h>
    22 #include <sys/epoll.h>
    21 #ifndef MAX_EVENTS
    23 #ifndef MAX_EVENTS
    22 #define MAX_EVENTS 64
    24 #define MAX_EVENTS 64
    23 #endif
    25 #endif
    24 #else
    26 #endif
       
    27 #ifdef USE_SELECT
    25 #include <sys/select.h>
    28 #include <sys/select.h>
    26 #endif
    29 #endif
    27 
    30 
    28 #include <lualib.h>
    31 #include <lualib.h>
    29 #include <lauxlib.h>
    32 #include <lauxlib.h>
    30 
    33 
    31 #ifdef USE_EPOLL
    34 #ifdef USE_EPOLL
    32 #define STATE_MT "util.poll<epoll>"
    35 #define STATE_MT "util.poll<epoll>"
    33 #else
    36 #endif
       
    37 #ifdef USE_SELECT
    34 #define STATE_MT "util.poll<select>"
    38 #define STATE_MT "util.poll<select>"
    35 #endif
    39 #endif
    36 
    40 
    37 #if (LUA_VERSION_NUM == 501)
    41 #if (LUA_VERSION_NUM == 501)
    38 #define luaL_setmetatable(L, tname) luaL_getmetatable(L, tname); lua_setmetatable(L, -2)
    42 #define luaL_setmetatable(L, tname) luaL_getmetatable(L, tname); lua_setmetatable(L, -2)
    47 typedef struct Lpoll_state {
    51 typedef struct Lpoll_state {
    48 	int processed;
    52 	int processed;
    49 #ifdef USE_EPOLL
    53 #ifdef USE_EPOLL
    50 	int epoll_fd;
    54 	int epoll_fd;
    51 	struct epoll_event events[MAX_EVENTS];
    55 	struct epoll_event events[MAX_EVENTS];
    52 #else
    56 #endif
       
    57 #ifdef USE_SELECT
    53 	fd_set wantread;
    58 	fd_set wantread;
    54 	fd_set wantwrite;
    59 	fd_set wantwrite;
    55 	fd_set readable;
    60 	fd_set readable;
    56 	fd_set writable;
    61 	fd_set writable;
    57 	fd_set all;
    62 	fd_set all;
    94 	}
    99 	}
    95 
   100 
    96 	lua_pushboolean(L, 1);
   101 	lua_pushboolean(L, 1);
    97 	return 1;
   102 	return 1;
    98 
   103 
    99 #else
   104 #endif
       
   105 #ifdef USE_SELECT
   100 
   106 
   101 	if(fd > FD_SETSIZE) {
   107 	if(fd > FD_SETSIZE) {
   102 		luaL_pushfail(L);
   108 		luaL_pushfail(L);
   103 		lua_pushstring(L, strerror(EBADF));
   109 		lua_pushstring(L, strerror(EBADF));
   104 		lua_pushinteger(L, EBADF);
   110 		lua_pushinteger(L, EBADF);
   167 		lua_pushstring(L, strerror(ret));
   173 		lua_pushstring(L, strerror(ret));
   168 		lua_pushinteger(L, ret);
   174 		lua_pushinteger(L, ret);
   169 		return 3;
   175 		return 3;
   170 	}
   176 	}
   171 
   177 
   172 #else
   178 #endif
       
   179 #ifdef USE_SELECT
   173 
   180 
   174 	if(!FD_ISSET(fd, &state->all)) {
   181 	if(!FD_ISSET(fd, &state->all)) {
   175 		luaL_pushfail(L);
   182 		luaL_pushfail(L);
   176 		lua_pushstring(L, strerror(ENOENT));
   183 		lua_pushstring(L, strerror(ENOENT));
   177 		lua_pushinteger(L, ENOENT);
   184 		lua_pushinteger(L, ENOENT);
   225 		lua_pushstring(L, strerror(ret));
   232 		lua_pushstring(L, strerror(ret));
   226 		lua_pushinteger(L, ret);
   233 		lua_pushinteger(L, ret);
   227 		return 3;
   234 		return 3;
   228 	}
   235 	}
   229 
   236 
   230 #else
   237 #endif
       
   238 #ifdef USE_SELECT
   231 
   239 
   232 	if(!FD_ISSET(fd, &state->all)) {
   240 	if(!FD_ISSET(fd, &state->all)) {
   233 		luaL_pushfail(L);
   241 		luaL_pushfail(L);
   234 		lua_pushstring(L, strerror(ENOENT));
   242 		lua_pushstring(L, strerror(ENOENT));
   235 		lua_pushinteger(L, ENOENT);
   243 		lua_pushinteger(L, ENOENT);
   262 		lua_pushboolean(L, event.events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR));
   270 		lua_pushboolean(L, event.events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR));
   263 		lua_pushboolean(L, event.events & EPOLLOUT);
   271 		lua_pushboolean(L, event.events & EPOLLOUT);
   264 		return 3;
   272 		return 3;
   265 	}
   273 	}
   266 
   274 
   267 #else
   275 #endif
       
   276 #ifdef USE_SELECT
   268 
   277 
   269 	for(int fd = state->processed + 1; fd < FD_SETSIZE; fd++) {
   278 	for(int fd = state->processed + 1; fd < FD_SETSIZE; fd++) {
   270 		if(FD_ISSET(fd, &state->readable) || FD_ISSET(fd, &state->writable) || FD_ISSET(fd, &state->err)) {
   279 		if(FD_ISSET(fd, &state->readable) || FD_ISSET(fd, &state->writable) || FD_ISSET(fd, &state->err)) {
   271 			lua_pushinteger(L, fd);
   280 			lua_pushinteger(L, fd);
   272 			lua_pushboolean(L, FD_ISSET(fd, &state->readable) | FD_ISSET(fd, &state->err));
   281 			lua_pushboolean(L, FD_ISSET(fd, &state->readable) | FD_ISSET(fd, &state->err));
   298 	lua_Number timeout = luaL_checknumber(L, 2);
   307 	lua_Number timeout = luaL_checknumber(L, 2);
   299 	luaL_argcheck(L, timeout >= 0, 1, "positive number expected");
   308 	luaL_argcheck(L, timeout >= 0, 1, "positive number expected");
   300 
   309 
   301 #ifdef USE_EPOLL
   310 #ifdef USE_EPOLL
   302 	ret = epoll_wait(state->epoll_fd, state->events, MAX_EVENTS, timeout * 1000);
   311 	ret = epoll_wait(state->epoll_fd, state->events, MAX_EVENTS, timeout * 1000);
   303 #else
   312 #endif
       
   313 #ifdef USE_SELECT
   304 	/*
   314 	/*
   305 	 * select(2) mutates the fd_sets passed to it so in order to not
   315 	 * select(2) mutates the fd_sets passed to it so in order to not
   306 	 * have to recreate it manually every time a copy is made.
   316 	 * have to recreate it manually every time a copy is made.
   307 	 */
   317 	 */
   308 	memcpy(&state->readable, &state->wantread, sizeof(fd_set));
   318 	memcpy(&state->readable, &state->wantread, sizeof(fd_set));
   339 	/*
   349 	/*
   340 	 * Search for the first ready FD and return it
   350 	 * Search for the first ready FD and return it
   341 	 */
   351 	 */
   342 #ifdef USE_EPOLL
   352 #ifdef USE_EPOLL
   343 	state->processed = ret;
   353 	state->processed = ret;
   344 #else
   354 #endif
       
   355 #ifdef USE_SELECT
   345 	state->processed = -1;
   356 	state->processed = -1;
   346 #endif
   357 #endif
   347 	return Lpushevent(L, state);
   358 	return Lpushevent(L, state);
   348 }
   359 }
   349 
   360 
   409 		lua_pushinteger(L, errno);
   420 		lua_pushinteger(L, errno);
   410 		return 3;
   421 		return 3;
   411 	}
   422 	}
   412 
   423 
   413 	state->epoll_fd = epoll_fd;
   424 	state->epoll_fd = epoll_fd;
   414 #else
   425 #endif
       
   426 #ifdef USE_SELECT
   415 	FD_ZERO(&state->wantread);
   427 	FD_ZERO(&state->wantread);
   416 	FD_ZERO(&state->wantwrite);
   428 	FD_ZERO(&state->wantwrite);
   417 	FD_ZERO(&state->readable);
   429 	FD_ZERO(&state->readable);
   418 	FD_ZERO(&state->writable);
   430 	FD_ZERO(&state->writable);
   419 	FD_ZERO(&state->all);
   431 	FD_ZERO(&state->all);