8 #if LUA_VERSION_NUM != 503
9 #error only Lua 5.3 supported
12 #define TIMEOUT_PUBLIC static
16 #define TIMEOUT_METANAME "struct timeout"
17 #define TIMEOUTS_METANAME "struct timeouts*"
19 static struct timeout
*
20 to_checkudata(lua_State
*L
, int index
)
22 return luaL_checkudata(L
, index
, TIMEOUT_METANAME
);
25 static struct timeouts
*
26 tos_checkudata(lua_State
*L
, int index
)
28 return *(struct timeouts
**)luaL_checkudata(L
, index
, TIMEOUTS_METANAME
);
32 tos_bind(lua_State
*L
, int tos_index
, int to_index
)
34 lua_getuservalue(L
, tos_index
);
35 lua_pushlightuserdata(L
, to_checkudata(L
, to_index
));
36 lua_pushvalue(L
, to_index
);
42 tos_unbind(lua_State
*L
, int tos_index
, int to_index
)
44 lua_getuservalue(L
, tos_index
);
45 lua_pushlightuserdata(L
, to_checkudata(L
, to_index
));
52 to__index(lua_State
*L
)
54 struct timeout
*to
= to_checkudata(L
, 1);
56 if (lua_type(L
, 2 == LUA_TSTRING
)) {
57 const char *key
= lua_tostring(L
, 2);
59 if (!strcmp(key
, "flags")) {
60 lua_pushinteger(L
, to
->flags
);
63 } else if (!strcmp(key
, "expires")) {
64 lua_pushinteger(L
, to
->expires
);
70 if (LUA_TNIL
!= lua_getuservalue(L
, 1)) {
72 if (LUA_TNIL
!= lua_rawget(L
, -2))
77 if (LUA_TNIL
!= lua_rawget(L
, lua_upvalueindex(1)))
84 to__newindex(lua_State
*L
)
86 if (LUA_TNIL
== lua_getuservalue(L
, 1)) {
89 lua_setuservalue(L
, 1);
102 struct timeout
*to
= to_checkudata(L
, 1);
105 * NB: On script exit it's possible for a timeout to still be
106 * associated with a timeouts object, particularly when the timeouts
107 * object was created first.
117 int flags
= luaL_optinteger(L
, 1, 0);
120 to
= lua_newuserdata(L
, sizeof *to
);
121 timeout_init(to
, flags
);
122 luaL_setmetatable(L
, TIMEOUT_METANAME
);
127 static const luaL_Reg to_methods
[] = {
131 static const luaL_Reg to_metatable
[] = {
132 { "__index", &to__index
},
133 { "__newindex", &to__newindex
},
138 static const luaL_Reg to_globals
[] = {
144 to_newmetatable(lua_State
*L
)
146 if (luaL_newmetatable(L
, TIMEOUT_METANAME
)) {
148 * fill metamethod table, capturing the methods table as an
149 * upvalue for use by __index metamethod
151 luaL_newlib(L
, to_methods
);
152 luaL_setfuncs(L
, to_metatable
, 1);
157 luaopen_timeout(lua_State
*L
)
161 luaL_newlib(L
, to_globals
);
162 lua_pushinteger(L
, TIMEOUT_INT
);
163 lua_setfield(L
, -2, "INT");
164 lua_pushinteger(L
, TIMEOUT_ABS
);
165 lua_setfield(L
, -2, "ABS");
171 tos_update(lua_State
*L
)
173 struct timeouts
*T
= tos_checkudata(L
, 1);
174 lua_Number n
= luaL_checknumber(L
, 2);
176 timeouts_update(T
, timeouts_f2i(T
, n
));
184 tos_step(lua_State
*L
)
186 struct timeouts
*T
= tos_checkudata(L
, 1);
187 lua_Number n
= luaL_checknumber(L
, 2);
189 timeouts_step(T
, timeouts_f2i(T
, n
));
197 tos_timeout(lua_State
*L
)
199 struct timeouts
*T
= tos_checkudata(L
, 1);
201 lua_pushnumber(L
, timeouts_i2f(T
, timeouts_timeout(T
)));
207 tos_add(lua_State
*L
)
209 struct timeouts
*T
= tos_checkudata(L
, 1);
210 struct timeout
*to
= to_checkudata(L
, 2);
211 lua_Number timeout
= luaL_checknumber(L
, 3);
214 timeouts_addf(T
, to
, timeout
);
216 return lua_pushvalue(L
, 1), 1;
220 tos_del(lua_State
*L
)
222 struct timeouts
*T
= tos_checkudata(L
, 1);
223 struct timeout
*to
= to_checkudata(L
, 2);
228 return lua_pushvalue(L
, 1), 1;
232 tos_get(lua_State
*L
)
234 struct timeouts
*T
= tos_checkudata(L
, 1);
237 if (!(to
= timeouts_get(T
)))
240 lua_getuservalue(L
, 1);
241 lua_rawgetp(L
, -1, to
);
243 if (!timeout_pending(to
))
244 tos_unbind(L
, 1, lua_absindex(L
, -1));
250 tos_pending(lua_State
*L
)
252 struct timeouts
*T
= tos_checkudata(L
, 1);
254 lua_pushboolean(L
, timeouts_pending(T
));
260 tos_expired(lua_State
*L
)
262 struct timeouts
*T
= tos_checkudata(L
, 1);
264 lua_pushboolean(L
, timeouts_expired(T
));
270 tos_check(lua_State
*L
)
272 struct timeouts
*T
= tos_checkudata(L
, 1);
274 lua_pushboolean(L
, timeouts_check(T
, NULL
));
280 tos__next(lua_State
*L
)
282 struct timeouts
*T
= tos_checkudata(L
, lua_upvalueindex(1));
283 struct timeouts_it
*it
= lua_touserdata(L
, lua_upvalueindex(2));
286 if (!(to
= timeouts_next(T
, it
)))
289 lua_getuservalue(L
, lua_upvalueindex(1));
290 lua_rawgetp(L
, -1, to
);
296 tos_timeouts(lua_State
*L
)
298 int flags
= luaL_checkinteger(L
, 2);
299 struct timeouts_it
*it
;
301 tos_checkudata(L
, 1);
303 it
= lua_newuserdata(L
, sizeof *it
);
304 TIMEOUTS_IT_INIT(it
, flags
);
305 lua_pushcclosure(L
, &tos__next
, 2);
311 tos__gc(lua_State
*L
)
313 struct timeouts
**tos
= luaL_checkudata(L
, 1, TIMEOUTS_METANAME
);
316 TIMEOUTS_FOREACH(to
, *tos
, TIMEOUTS_ALL
) {
317 timeouts_del(*tos
, to
);
320 timeouts_close(*tos
);
327 tos_new(lua_State
*L
)
329 timeout_t hz
= luaL_optinteger(L
, 1, 0);
333 T
= lua_newuserdata(L
, sizeof *T
);
334 luaL_setmetatable(L
, TIMEOUTS_METANAME
);
337 lua_setuservalue(L
, -2);
339 if (!(*T
= timeouts_open(hz
, &error
)))
340 return luaL_error(L
, "%s", strerror(error
));
345 static const luaL_Reg tos_methods
[] = {
346 { "update", &tos_update
},
347 { "step", &tos_step
},
348 { "timeout", &tos_timeout
},
352 { "pending", &tos_pending
},
353 { "expired", &tos_expired
},
354 { "check", &tos_check
},
355 { "timeouts", &tos_timeouts
},
359 static const luaL_Reg tos_metatable
[] = {
360 { "__gc", &tos__gc
},
364 static const luaL_Reg tos_globals
[] = {
370 tos_newmetatable(lua_State
*L
)
372 if (luaL_newmetatable(L
, TIMEOUTS_METANAME
)) {
373 luaL_setfuncs(L
, tos_metatable
, 0);
374 luaL_newlib(L
, tos_methods
);
375 lua_setfield(L
, -2, "__index");
380 luaopen_timeouts(lua_State
*L
)
385 luaL_newlib(L
, tos_globals
);
386 lua_pushinteger(L
, TIMEOUTS_PENDING
);
387 lua_setfield(L
, -2, "PENDING");
388 lua_pushinteger(L
, TIMEOUTS_EXPIRED
);
389 lua_setfield(L
, -2, "EXPIRED");
390 lua_pushinteger(L
, TIMEOUTS_ALL
);
391 lua_setfield(L
, -2, "ALL");
392 lua_pushinteger(L
, TIMEOUTS_CLEAR
);
393 lua_setfield(L
, -2, "CLEAR");