180 lines
4.4 KiB
C
180 lines
4.4 KiB
C
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <lua5.3/lualib.h>
|
|
#include <lua5.3/lauxlib.h>
|
|
#include <time.h>
|
|
|
|
#include "oct_timer.h"
|
|
#include "oct_log.h"
|
|
|
|
struct oct_timer_list_ oct_timer_list;
|
|
int64_t prev_millis;
|
|
|
|
int oct_timer_list_initialize() {
|
|
OCT_LOG_INFO("Initializing timer list")
|
|
oct_timer_list.size = 0;
|
|
oct_timer_list.first = NULL;
|
|
oct_timer_list.last = NULL;
|
|
|
|
struct timespec now;
|
|
timespec_get(&now, TIME_UTC);
|
|
prev_millis = ((int64_t) now.tv_sec) * 1000 + ((int64_t) now.tv_nsec) / 1000000;
|
|
|
|
|
|
return 1;
|
|
}
|
|
|
|
int oct_timer_list_deinitialize() {
|
|
struct oct_timer_elem* crawler = oct_timer_list.first;
|
|
while (crawler != NULL) {
|
|
struct oct_timer_elem* temp = crawler->next;
|
|
free(crawler);
|
|
crawler = temp;
|
|
}
|
|
oct_timer_list.first = NULL;
|
|
oct_timer_list.last = NULL;
|
|
oct_timer_list.size = 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int oct_timer_register(lua_State *L) {
|
|
// Gather the arguments
|
|
char id[OCT_TIMER_MAXIMUM_ID_LENGTH];
|
|
int64_t millis;
|
|
char function[OCT_TIMER_MAXIMUM_ID_LENGTH];
|
|
char argument[OCT_TIMER_MAXIMUM_ID_LENGTH];
|
|
strncpy(id, luaL_checkstring(L, -4), OCT_TIMER_MAXIMUM_ID_LENGTH);
|
|
millis = luaL_checkinteger(L, -3);
|
|
strncpy(function, luaL_checkstring(L, -2), OCT_TIMER_MAXIMUM_FUNCTION_NAME_LENGTH);
|
|
strncpy(argument, luaL_checkstring(L, -1), OCT_TIMER_MAXIMUM_ARGUMENT_LENGTH);
|
|
|
|
// Check for any duplicate ids in the list
|
|
if (oct_timer_find(id)) {
|
|
OCT_LOG_ERROR("Tried to register a timer with a duplicate ID");
|
|
lua_pushnil(L);
|
|
return 1;
|
|
}
|
|
|
|
// We're good to go, insert at the end
|
|
struct oct_timer_elem* e = (struct oct_timer_elem*)malloc(sizeof(struct oct_timer_elem));
|
|
strncpy(e->id, id, OCT_TIMER_MAXIMUM_ID_LENGTH);
|
|
e->millis = millis;
|
|
strncpy(e->lua_function, function, OCT_TIMER_MAXIMUM_FUNCTION_NAME_LENGTH);
|
|
strncpy(e->lua_argument, argument, OCT_TIMER_MAXIMUM_ARGUMENT_LENGTH);
|
|
if (!oct_timer_list.first) {
|
|
oct_timer_list.first = e;
|
|
}
|
|
e->next = NULL;
|
|
e->prev = oct_timer_list.last;
|
|
if (oct_timer_list.last) {
|
|
oct_timer_list.last->next = e;
|
|
}
|
|
oct_timer_list.last = e;
|
|
oct_timer_list.size++;
|
|
|
|
// not sure if i have to return something
|
|
return 0;
|
|
}
|
|
|
|
struct oct_timer_elem* oct_timer_find(char* id) {
|
|
struct oct_timer_elem* crawler = oct_timer_list.first;
|
|
while (crawler != NULL) {
|
|
if (strncmp(id, crawler->id, OCT_TIMER_MAXIMUM_ID_LENGTH) == 0) {
|
|
return crawler;
|
|
}
|
|
crawler = crawler->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int oct_timer_unregister(char* id, int do_free) {
|
|
struct oct_timer_elem* e = oct_timer_find(id);
|
|
if (!e) {
|
|
OCT_LOG_WARNING("Tried to unregister a nonexistent timer");
|
|
return 0;
|
|
}
|
|
|
|
if (e == oct_timer_list.first) {
|
|
oct_timer_list.first = e->next;
|
|
if (e->next) {
|
|
e->next->prev = NULL;
|
|
}
|
|
}
|
|
else if (e == oct_timer_list.last) {
|
|
oct_timer_list.last = e->prev;
|
|
if (e->prev) {
|
|
e->prev->next = NULL;
|
|
}
|
|
}
|
|
else {
|
|
e->next->prev = e->prev;
|
|
e->prev->next = e->next;
|
|
}
|
|
|
|
oct_timer_list.size--;
|
|
|
|
if (do_free) {
|
|
free(e);
|
|
}
|
|
|
|
// Not sure if I have to return something
|
|
return 0;
|
|
}
|
|
|
|
int oct_timer_unregister_lua(lua_State *L) {
|
|
char id[OCT_TIMER_MAXIMUM_ID_LENGTH];
|
|
strncpy(id, luaL_checkstring(L, -1), OCT_TIMER_MAXIMUM_ID_LENGTH);
|
|
|
|
int res = oct_timer_unregister(id, 1);
|
|
if (!res) {
|
|
lua_pushnil(L);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int oct_timer_initialize_lua(lua_State *L) {
|
|
OCT_LOG_INFO("Exporting timer lua functions");
|
|
lua_pushcfunction(L, oct_timer_register);
|
|
lua_setglobal(L, "oct_timer_register");
|
|
lua_pushcfunction(L, oct_timer_unregister_lua);
|
|
lua_setglobal(L, "oct_timer_unregister");
|
|
// I don't think we need a metatable...
|
|
return 1;
|
|
}
|
|
|
|
int oct_timer_tick(lua_State *L) {
|
|
struct timespec now;
|
|
timespec_get(&now, TIME_UTC);
|
|
int64_t millis = ((int64_t) now.tv_sec) * 1000 + ((int64_t) now.tv_nsec) / 1000000;
|
|
int64_t elapsed = millis - prev_millis;
|
|
|
|
struct oct_timer_elem* crawler = oct_timer_list.first;
|
|
while (crawler != NULL) {
|
|
crawler->millis -= elapsed;
|
|
if (crawler->millis <= 0) {
|
|
struct oct_timer_elem* temp = crawler;
|
|
crawler = crawler->next;
|
|
// First, remove the timer
|
|
// lua can add a timer at the end of the function, don't want to complicate things by making the developer come up with a unique name
|
|
// So we unregister it, but don't free it yet
|
|
oct_timer_unregister(temp->id, 0);
|
|
|
|
// call lua function with argument
|
|
lua_getglobal(L, temp->lua_function);
|
|
lua_pushstring(L, temp->lua_argument);
|
|
lua_call(L, 1, 0);
|
|
|
|
// Now free the timer
|
|
free(temp);
|
|
}
|
|
else {
|
|
crawler = crawler->next;
|
|
}
|
|
}
|
|
|
|
prev_millis = millis;
|
|
return 0;
|
|
}
|