]>
jfr.im git - irc/quakenet/newserv.git/blob - lua/luascheduler.c
1 #include "../core/schedule.h"
2 #include "../core/error.h"
5 #define SCHEDULER_METATABLE "newserv.scheduler"
6 #define SCHEDULER_ENTRY_METATABLE "newserv.schedulerentry"
8 static int lua_scheduler_new(lua_State
*ps
) {
10 lua_list
*ll
= lua_listfromstate(ps
);
14 result
= (lua_scheduler
*)lua_newuserdata(ps
, sizeof(lua_scheduler
));
18 luaL_getmetatable(ps
, SCHEDULER_METATABLE
);
19 lua_setmetatable(ps
, -2);
22 result
->entries
= NULL
;
24 result
->next
= ll
->schedulers
;
25 ll
->schedulers
= result
;
30 static void remove_entry(lua_scheduler_entry
*entry
) {
32 entry
->prev
->next
= entry
->next
;
34 entry
->sched
->entries
= entry
->next
;
38 entry
->next
->prev
= entry
->prev
;
40 /* no tail pointer! */
48 static void free_entry(lua_scheduler_entry
*entry
) {
49 luaL_unref(entry
->sched
->ps
, LUA_REGISTRYINDEX
, entry
->ref
);
53 static int valid_entry(lua_scheduler_entry
*entry
) {
54 if(!entry
|| !entry
->psch
) {
55 Error("lua", ERR_WARNING
, "Invalid scheduler entry: %p", entry
);
62 static void scheduler_exec(void *arg
) {
63 lua_scheduler_entry
*entry
= (lua_scheduler_entry
*)arg
;
65 if(!valid_entry(entry
))
70 _lua_vpcall(entry
->sched
->ps
, (void *)(long)entry
->ref
, LUA_POINTERMODE
, "");
75 static lua_scheduler
*lua_toscheduler(lua_State
*ps
, int arg
) {
76 void *ud
= luaL_checkudata(ps
, 1, SCHEDULER_METATABLE
);
80 return (lua_scheduler
*)ud
;
83 static int lua_scheduler_add(lua_State
*ps
) {
84 lua_scheduler_entry
*entry
;
87 if(!lua_isuserdata(ps
, 1) || !lua_isint(ps
, 2) || !lua_isfunction(ps
, 3))
90 sched
= (lua_scheduler
*)lua_toscheduler(ps
, 1);
94 entry
= (lua_scheduler_entry
*)malloc(sizeof(lua_scheduler_entry
));
98 entry
->ref
= luaL_ref(ps
, LUA_REGISTRYINDEX
);
100 entry
->psch
= scheduleoneshot(lua_toint(ps
, 2), scheduler_exec
, entry
);
102 luaL_unref(ps
, LUA_REGISTRYINDEX
, entry
->ref
);
108 entry
->next
= sched
->entries
;
110 /* note: we have no tail pointer */
113 sched
->entries
->prev
= entry
;
115 sched
->entries
= entry
;
118 lua_pushlightuserdata(ps
, entry
);
122 static void delete_entry(lua_scheduler_entry
*entry
) {
123 deleteschedule(entry
->psch
, scheduler_exec
, entry
);
128 static int lua_scheduler_remove(lua_State
*ps
) {
129 lua_scheduler_entry
*entry
;
131 if(!lua_islightuserdata(ps
, 1))
132 LUA_RETURN(ps
, LUA_FAIL
);
134 entry
= (lua_scheduler_entry
*)lua_topointer(ps
, 1);
136 if(!valid_entry(entry
))
137 LUA_RETURN(ps
, LUA_FAIL
);
141 LUA_RETURN(ps
, LUA_OK
);
144 static int lua_scheduler_count(lua_State
*ps
) {
145 lua_scheduler
*sched
;
147 if(!lua_islightuserdata(ps
, 1))
150 sched
= (lua_scheduler
*)lua_topointer(ps
, 1);
151 lua_pushint(ps
, sched
->count
);
156 static void scheduler_free(lua_list
*ll
, lua_scheduler
*sched
) {
157 lua_scheduler
*prev
, *l
;
162 while(sched
->entries
)
163 delete_entry(sched
->entries
);
165 for(prev
=NULL
,l
=ll
->schedulers
;l
;prev
=l
,l
=l
->next
) {
170 prev
->next
= sched
->next
;
172 ll
->schedulers
= sched
->next
;
181 void lua_scheduler_freeall(lua_list
*ll
) {
182 while(ll
->schedulers
)
183 scheduler_free(ll
, ll
->schedulers
);
186 /* called at GC time only */
187 static int lua_scheduler_free(lua_State
*ps
) {
188 lua_list
*ll
= lua_listfromstate(ps
);
189 lua_scheduler
*sched
;
191 if(!ll
|| !lua_isuserdata(ps
, 1))
194 sched
= lua_toscheduler(ps
, 1);
198 scheduler_free(ll
, sched
);
203 void lua_registerschedulercommands(lua_State
*ps
) {
204 lua_register(ps
, "raw_scheduler_new", lua_scheduler_new
);
205 lua_register(ps
, "raw_scheduler_count", lua_scheduler_count
);
206 lua_register(ps
, "raw_scheduler_add", lua_scheduler_add
);
207 lua_register(ps
, "raw_scheduler_remove", lua_scheduler_remove
);
209 luaL_newmetatable(ps
, SCHEDULER_METATABLE
);
210 lua_pushcfunction(ps
, lua_scheduler_free
);
211 lua_setfield(ps
, -2, "__gc");