Lua: Add on_idle() and on_timer()

This commit is contained in:
Ilari Liusvaara 2012-03-06 13:48:39 +02:00
parent 528628b233
commit 44233e3897
5 changed files with 134 additions and 11 deletions

View file

@ -15,6 +15,8 @@ void push_keygroup_parameters(lua_State* LS, const struct keygroup::parameters&
extern lua_render_context* lua_render_ctx;
extern controller_frame* lua_input_controllerdata;
extern bool lua_booted_flag;
extern uint64_t lua_idle_hook_time;
extern uint64_t lua_timer_hook_time;
template<typename T>
T get_numeric_argument(lua_State* LS, unsigned argindex, const char* fname)

View file

@ -77,6 +77,8 @@ void lua_callback_do_frame_emulated() throw();
void lua_callback_do_rewind() throw();
void lua_callback_do_readwrite() throw();
void lua_callback_startup() throw();
void lua_callback_do_idle() throw();
void lua_callback_do_timer() throw();
void lua_callback_pre_load(const std::string& name) throw();
void lua_callback_err_load(const std::string& name) throw();
void lua_callback_post_load(const std::string& name, bool was_state) throw();
@ -87,6 +89,11 @@ void lua_callback_snoop_input(uint32_t port, uint32_t controller, uint32_t index
void lua_callback_quit() throw();
void lua_callback_keyhook(const std::string& key, const struct keygroup::parameters& p) throw();
#define LUA_TIMED_HOOK_IDLE 0
#define LUA_TIMED_HOOK_TIMER 1
uint64_t lua_timed_hook(int timer) throw();
extern bool lua_supported;
extern bool lua_requests_repaint;
extern bool lua_requests_subframe_paint;

View file

@ -13,6 +13,8 @@ void lua_callback_do_rewind() throw() {}
void lua_callback_do_frame_emulated() throw() {}
void lua_callback_do_readwrite() throw() {}
void lua_callback_startup() throw() {}
void lua_callback_do_idle() throw() {}
void lua_callback_do_timer() throw() {}
void lua_callback_pre_load(const std::string& name) throw() {}
void lua_callback_err_load(const std::string& name) throw() {}
void lua_callback_post_load(const std::string& name, bool was_state) throw() {}
@ -24,6 +26,9 @@ void lua_callback_quit() throw() {}
void lua_callback_keyhook(const std::string& key, const struct keygroup::parameters& p) throw() {}
void init_lua() throw() {}
void quit_lua() throw() {}
uint64_t lua_timed_hook(int timer) throw() { return 0x7EFFFFFFFFFFFFFFULL; }
bool lua_requests_repaint = false;
bool lua_requests_subframe_paint = false;
bool lua_supported = false;
@ -45,6 +50,9 @@ extern "C" {
#include <lualib.h>
}
uint64_t lua_idle_hook_time = 0x7EFFFFFFFFFFFFFFULL;
uint64_t lua_timer_hook_time = 0x7EFFFFFFFFFFFFFFULL;
namespace
{
globalwrap<std::map<std::string, lua_function*>> functions;
@ -405,6 +413,22 @@ void lua_callback_do_rewind() throw()
run_lua_cb(0);
}
void lua_callback_do_idle() throw()
{
lua_idle_hook_time = 0x7EFFFFFFFFFFFFFFULL;
if(!callback_exists("on_idle"))
return;
run_lua_cb(0);
}
void lua_callback_do_timer() throw()
{
lua_timer_hook_time = 0x7EFFFFFFFFFFFFFFULL;
if(!callback_exists("on_timer"))
return;
run_lua_cb(0);
}
void lua_callback_do_frame_emulated() throw()
{
if(!callback_exists("on_frame_emulated"))
@ -552,6 +576,21 @@ void quit_lua() throw()
lua_close(lua_initialized);
}
#define LUA_TIMED_HOOK_IDLE 0
#define LUA_TIMED_HOOK_TIMER 1
uint64_t lua_timed_hook(int timer) throw()
{
switch(timer) {
case LUA_TIMED_HOOK_IDLE:
return lua_idle_hook_time;
case LUA_TIMED_HOOK_TIMER:
return lua_timer_hook_time;
}
}
bool lua_requests_repaint = false;
bool lua_requests_subframe_paint = false;
bool lua_supported = true;

View file

@ -1,10 +1,12 @@
#include "core/command.hpp"
#include "core/dispatch.hpp"
#include "core/framerate.hpp"
#include "core/lua.hpp"
#include "core/misc.hpp"
#include "core/render.hpp"
#include "core/window.hpp"
#include "library/string.hpp"
#include "library/minmax.hpp"
#include <fstream>
#include <iostream>
@ -118,6 +120,8 @@ keypress::keypress(modifier_set mod, keygroup& _key, keygroup& _key2, short _val
namespace
{
bool queue_function_run = false;
function_ptr_command<> identify_key("show-plugins", "Show plugins in use",
"Syntax: show-plugins\nShows plugins in use.\n",
[]() throw(std::bad_alloc, std::runtime_error) {
@ -381,6 +385,7 @@ namespace
if(k.key2)
k.key2->set_position(k.value, k.modifiers);
queue_lock->lock();
queue_function_run = true;
}
//Flush commands.
while(!commands.empty()) {
@ -389,6 +394,7 @@ namespace
queue_lock->unlock();
command::invokeC(c);
queue_lock->lock();
queue_function_run = true;
}
//Flush functions.
while(!functions.empty()) {
@ -398,6 +404,7 @@ namespace
f.first(f.second);
queue_lock->lock();
++functions_executed;
queue_function_run = true;
}
queue_condition->signal();
} catch(std::bad_alloc& e) {
@ -409,28 +416,62 @@ namespace
if(!unlocked)
queue_lock->unlock();
}
uint64_t on_idle_time;
uint64_t on_timer_time;
void reload_lua_timers()
{
on_idle_time = lua_timed_hook(LUA_TIMED_HOOK_IDLE);
on_timer_time = lua_timed_hook(LUA_TIMED_HOOK_TIMER);
queue_function_run = false;
}
}
#define MAXWAIT 10000
#define MAXWAIT 5000000ULL
void platform::flush_command_queue() throw()
{
reload_lua_timers();
queue_function_run = false;
if(modal_pause || normal_pause)
freeze_time(get_utime());
init_threading();
bool run_idle = false;
while(true) {
uint64_t now = get_utime();
if(now >= on_timer_time) {
lua_callback_do_timer();
reload_lua_timers();
}
if(run_idle) {
lua_callback_do_idle();
reload_lua_timers();
run_idle = false;
}
mutex::holder h(*queue_lock);
internal_run_queues(true);
if(!pausing_allowed)
break;
uint64_t now = get_utime();
if(queue_function_run)
reload_lua_timers();
now = get_utime();
uint64_t waitleft = 0;
waitleft = (now < continue_time) ? (continue_time - now) : 0;
waitleft = (modal_pause || normal_pause) ? MAXWAIT : waitleft;
waitleft = (waitleft > MAXWAIT) ? MAXWAIT : waitleft;
if(waitleft > 0)
queue_condition->wait(waitleft);
else
waitleft = min(waitleft, MAXWAIT);
if(waitleft > 0) {
if(now >= on_idle_time) {
run_idle = true;
waitleft = 0;
}
if(on_idle_time >= now)
waitleft = min(waitleft, on_idle_time - now);
if(on_timer_time >= now)
waitleft = min(waitleft, on_timer_time - now);
if(waitleft > 0)
queue_condition->wait(waitleft);
} else
break;
//If we had to wait, check queues at least once more.
}
@ -445,18 +486,41 @@ void platform::set_paused(bool enable) throw()
void platform::wait(uint64_t usec) throw()
{
reload_lua_timers();
continue_time = get_utime() + usec;
init_threading();
bool run_idle = false;
while(true) {
uint64_t now = get_utime();
if(now >= on_timer_time) {
lua_callback_do_timer();
reload_lua_timers();
}
if(run_idle) {
lua_callback_do_idle();
run_idle = false;
reload_lua_timers();
}
mutex::holder h(*queue_lock);
internal_run_queues(true);
uint64_t now = get_utime();
if(queue_function_run)
reload_lua_timers();
now = get_utime();
uint64_t waitleft = 0;
waitleft = (now < continue_time) ? (continue_time - now) : 0;
waitleft = (waitleft > MAXWAIT) ? MAXWAIT : waitleft;
if(waitleft > 0)
queue_condition->wait(waitleft);
else
waitleft = min(MAXWAIT, waitleft);
if(waitleft > 0) {
if(now >= on_idle_time) {
run_idle = true;
waitleft = 0;
}
if(on_idle_time >= now)
waitleft = min(waitleft, on_idle_time - now);
if(on_timer_time >= now)
waitleft = min(waitleft, on_timer_time - now);
if(waitleft > 0)
queue_condition->wait(waitleft);
} else
return;
}
}

View file

@ -58,4 +58,15 @@ namespace
lua_pushnumber(LS, t % 1000000);
return 2;
});
function_ptr_luafun lua_idle_time("set_idle_timeout", [](lua_State* LS, const std::string& fname) -> int {
lua_idle_hook_time = get_utime() + get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
return 0;
});
function_ptr_luafun lua_timer_time("set_timer_timeout", [](lua_State* LS, const std::string& fname) -> int {
lua_timer_hook_time = get_utime() + get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
return 0;
});
}