summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-07-25 10:58:33 +0200
committerNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-07-25 10:58:33 +0200
commit8bb55a25830c3f7d2c67c8571786b6806fb8f515 (patch)
tree9ff9531f33c82fa1dd23695982c8d1f53dcbd1ad /includes
parentb92f0cee87ae48608c279d7192872b83a29b8fc5 (diff)
Lua now properly yields when an operation throws EAgain.
Diffstat (limited to 'includes')
-rw-r--r--includes/BLua.h44
1 files changed, 44 insertions, 0 deletions
diff --git a/includes/BLua.h b/includes/BLua.h
index bf7caae..e11c3fb 100644
--- a/includes/BLua.h
+++ b/includes/BLua.h
@@ -1,5 +1,7 @@
#pragma once
+#include <functional>
+
extern "C" {
#include <lua.h>
#include <lauxlib.h>
@@ -7,6 +9,7 @@ extern "C" {
#include <Exceptions.h>
#include <Handle.h>
+#include <Task.h>
namespace Balau {
@@ -271,8 +274,16 @@ template <class T>
T * LuaObjectFactory::getMe(Lua & L, int idx) { return L.recast<T>(idx); }
class LuaHelpersBase {
+ public:
+ static bool resume(Lua & L);
+ static Events::BaseEvent * getEvent(Lua & L);
protected:
static void validate(const lua_functypes_t & entry, bool method, int n, Lua & L, const char * className);
+ static void pushContext(Lua & L, std::function<int(Lua & L)> context, Events::BaseEvent * evt);
+ private:
+ LuaHelpersBase(std::function<int(Lua & L)> context, Events::BaseEvent * evt) : m_context(context), m_evt(evt) { }
+ std::function<int(Lua & L)> m_context;
+ Events::BaseEvent * m_evt;
};
template <class T>
@@ -280,6 +291,39 @@ class LuaHelpers : public LuaHelpersBase {
public:
static int method_multiplex(int caller, lua_State * __L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) {
Lua L(__L);
+ return method_multiplex(caller, L, proceed, proceed_static, tab, method);
+ }
+
+ private:
+ static int method_multiplex(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) {
+ int r;
+
+ try {
+ r = method_multiplex_internal(caller, L, proceed, proceed_static, tab, method);
+ }
+ catch (EAgain e) {
+ pushContext(L, [caller, proceed, proceed_static, tab, method](Lua & L) -> int { return method_multiplex_resume(caller, L, proceed, proceed_static, tab, method); }, e.getEvent());
+ r = L.yield(L.gettop());
+ }
+
+ return r;
+ }
+
+ static int method_multiplex_resume(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) {
+ int r;
+
+ try {
+ r = method_multiplex_internal(caller, L, proceed, proceed_static, tab, method);
+ }
+ catch (EAgain e) {
+ pushContext(L, [caller, proceed, proceed_static, tab, method](Lua & L) -> int { return method_multiplex_resume(caller, L, proceed, proceed_static, tab, method); }, e.getEvent());
+ r = -1;
+ }
+
+ return r;
+ }
+
+ static int method_multiplex_internal(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) {
int add = method ? 1 : 0;
int n = L.gettop() - add;
T * obj = 0;