From 70c45d6131e6ae251e3e5f010195950f9aaef78a Mon Sep 17 00:00:00 2001 From: Brett Langdon Date: Tue, 1 Jan 2013 10:25:03 -0500 Subject: [PATCH] added async versions of status and gc, made functions specific to LuaState objects I added a required argument to LuaState(), a string 'name', this is used to add to the key of the functions when storing them in the global map, this is so that two different LuaState objects can have functions with the same names that do not collide, as well, it means registering a function for one LuaState does not make it available to all the others. --- src/luastate.cc | 148 ++++++++++++++++++++++++++++++++++++++++++++++-- src/luastate.h | 9 ++- 2 files changed, 151 insertions(+), 6 deletions(-) diff --git a/src/luastate.cc b/src/luastate.cc index 083efa2..7a0b0f9 100644 --- a/src/luastate.cc +++ b/src/luastate.cc @@ -15,6 +15,15 @@ struct async_baton{ LuaState* state; }; +struct simple_baton{ + bool has_cb; + Persistent callback; + int data; + int result; + LuaState* state; +}; + + void do_file(uv_work_t *req){ async_baton* baton = static_cast(req->data); @@ -25,6 +34,43 @@ void do_file(uv_work_t *req){ } +void do_gc(uv_work_t *req){ + simple_baton* baton = static_cast(req->data); + + baton->result = lua_gc(baton->state->lua_, baton->data, 0); +} + + +void do_status(uv_work_t *req){ + simple_baton* baton = static_cast(req->data); + + baton->result = lua_status(baton->state->lua_); +} + + +void simple_after(uv_work_t *req){ + HandleScope scope; + + simple_baton* baton = static_cast(req->data); + + const int argc = 1; + Local argv[] = { Number::New(baton->result) }; + + TryCatch try_catch; + + if(baton->has_cb){ + baton->callback->Call(Context::GetCurrent()->Global(), argc, argv); + } + + baton->callback.Dispose(); + delete baton; + delete req; + + if(try_catch.HasCaught()){ + node::FatalException(try_catch); + } +} + void do_string(uv_work_t *req){ async_baton* baton = static_cast(req->data); @@ -65,7 +111,7 @@ void async_after(uv_work_t *req){ delete baton; delete req; - if (try_catch.HasCaught()) { + if(try_catch.HasCaught()){ node::FatalException(try_catch); } } @@ -97,10 +143,19 @@ void LuaState::Init(Handle target){ tpl->PrototypeTemplate()->Set(String::NewSymbol("status"), FunctionTemplate::New(Status)->GetFunction()); - tpl->PrototypeTemplate()->Set(String::NewSymbol("close"), - FunctionTemplate::New(Close)->GetFunction()); + tpl->PrototypeTemplate()->Set(String::NewSymbol("statusSync"), + FunctionTemplate::New(StatusSync)->GetFunction()); + tpl->PrototypeTemplate()->Set(String::NewSymbol("collectGarbage"), FunctionTemplate::New(CollectGarbage)->GetFunction()); + tpl->PrototypeTemplate()->Set(String::NewSymbol("collectGarbageSync"), + FunctionTemplate::New(CollectGarbageSync)->GetFunction()); + + tpl->PrototypeTemplate()->Set(String::NewSymbol("close"), + FunctionTemplate::New(Close)->GetFunction()); + tpl->PrototypeTemplate()->Set(String::NewSymbol("getName"), + FunctionTemplate::New(GetName)->GetFunction()); + tpl->PrototypeTemplate()->Set(String::NewSymbol("registerFunction"), FunctionTemplate::New(RegisterFunction)->GetFunction()); @@ -145,7 +200,16 @@ Handle LuaState::New(const Arguments& args){ return ThrowException(Exception::TypeError(String::New("LuaState Requires The 'new' Operator To Create An Instance"))); } + if(!args.Length() > 0){ + return ThrowException(Exception::TypeError(String::New("LuaState Requires 1 Argument"))); + } + + if(!args[0]->IsString()){ + return ThrowException(Exception::TypeError(String::New("LuaState First Argument Must Be A String"))); + } + LuaState* obj = new LuaState(); + obj->name_ = get_str(args[0]); obj->lua_ = lua_open(); luaL_openlibs(obj->lua_); obj->Wrap(args.This()); @@ -154,6 +218,14 @@ Handle LuaState::New(const Arguments& args){ } +Handle LuaState::GetName(const Arguments& args){ + HandleScope scope; + + LuaState* obj = ObjectWrap::Unwrap(args.This()); + return scope.Close(String::New(obj->name_)); +} + + Handle LuaState::DoFileSync(const Arguments& args){ HandleScope scope; @@ -341,6 +413,31 @@ Handle LuaState::Close(const Arguments& args){ Handle LuaState::Status(const Arguments& args){ + HandleScope scope; + LuaState* obj = ObjectWrap::Unwrap(args.This()); + simple_baton* baton = new simple_baton(); + baton->state = obj; + obj->Ref(); + + if(args.Length() > 0 && !args[0]->IsFunction()){ + ThrowException(Exception::TypeError(String::New("LuaState.status First Argument Must Be A Function"))); + return scope.Close(Undefined()); + } + + if(args.Length() > 0){ + baton->has_cb = true; + baton->callback = Persistent::New(Local::Cast(args[0])); + } + + uv_work_t *req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, do_status, simple_after); + + return scope.Close(Undefined()); +} + + +Handle LuaState::StatusSync(const Arguments& args){ HandleScope scope; LuaState* obj = ObjectWrap::Unwrap(args.This()); int status = lua_status(obj->lua_); @@ -362,6 +459,45 @@ Handle LuaState::CollectGarbage(const Arguments& args){ return scope.Close(Undefined()); } + LuaState* obj = ObjectWrap::Unwrap(args.This()); + int type = (int)args[0]->ToNumber()->Value(); + + simple_baton* baton = new simple_baton(); + baton->data = type; + baton->state = obj; + obj->Ref(); + + if(args.Length() > 1 && !args[1]->IsFunction()){ + ThrowException(Exception::TypeError(String::New("LuaState.collectGarbage Second Argument Must Be A Function"))); + return scope.Close(Undefined()); + } + + if(args.Length() > 1){ + baton->has_cb = true; + baton->callback = Persistent::New(Local::Cast(args[1])); + } + + uv_work_t *req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, do_gc, simple_after); + + return scope.Close(Undefined()); +} + + +Handle LuaState::CollectGarbageSync(const Arguments& args){ + HandleScope scope; + + if(args.Length() < 1){ + ThrowException(Exception::TypeError(String::New("LuaState.collectGarbageSync Requires 1 Argument"))); + return scope.Close(Undefined()); + } + + if(!args[0]->IsNumber()){ + ThrowException(Exception::TypeError(String::New("LuaSatte.collectGarbageSync Argument 1 Must Be A Number, try nodelua.GC.[TYPE]"))); + return scope.Close(Undefined()); + } + LuaState* obj = ObjectWrap::Unwrap(args.This()); int type = (int)args[0]->ToNumber()->Value(); int gc = lua_gc(obj->lua_, type, 0); @@ -392,9 +528,11 @@ Handle LuaState::RegisterFunction(const Arguments& args){ Persistent func = Persistent::New(Local::Cast(args[1])); char* func_name = get_str(args[0]); - functions[func_name] = func; + Local func_key = String::Concat(String::New(func_name), String::New(":")); + func_key = String::Concat(func_key, String::New(obj->name_)); + functions[get_str(func_key)] = func; - lua_pushstring(obj->lua_, func_name); + lua_pushstring(obj->lua_, get_str(func_key)); lua_pushcclosure(obj->lua_, CallFunction, 1); lua_setglobal(obj->lua_, func_name); diff --git a/src/luastate.h b/src/luastate.h index 95ba6c6..255a8e5 100644 --- a/src/luastate.h +++ b/src/luastate.h @@ -15,6 +15,7 @@ extern "C"{ class LuaState : public node::ObjectWrap{ public: lua_State* lua_; + char* name_; static void Init(v8::Handle target); static int CallFunction(lua_State* L); @@ -24,9 +25,15 @@ class LuaState : public node::ObjectWrap{ ~LuaState(); static v8::Handle New(const v8::Arguments& args); - static v8::Handle Status(const v8::Arguments& args); static v8::Handle Close(const v8::Arguments& args); + static v8::Handle GetName(const v8::Arguments& args); + static v8::Handle CollectGarbage(const v8::Arguments& args); + static v8::Handle CollectGarbageSync(const v8::Arguments& args); + + static v8::Handle Status(const v8::Arguments& args); + static v8::Handle StatusSync(const v8::Arguments& args); + static v8::Handle DoFileSync(const v8::Arguments& args); static v8::Handle DoFile(const v8::Arguments& args);