From 4dafefe46a72ba47468b13d011f8299055081b0f Mon Sep 17 00:00:00 2001 From: chai Date: Fri, 22 Oct 2021 23:59:54 +0800 Subject: *LuaBind --- Runtime/Lua/LuaBind/LuaBindClass.cpp | 2 + Runtime/Lua/LuaBind/LuaBindClass.hpp | 150 ++---- Runtime/Lua/LuaBind/LuaBindHelper.cpp | 0 Runtime/Lua/LuaBind/LuaBindHelper.h | 16 + Runtime/Lua/LuaBind/LuaBindMemberRef.h | 2 - Runtime/Lua/LuaBind/LuaBindRef.cpp | 72 ++- Runtime/Lua/LuaBind/LuaBindRef.h | 21 +- Runtime/Lua/LuaBind/LuaBindRefTable.cpp | 34 +- Runtime/Lua/LuaBind/LuaBindRefTable.h | 15 +- Runtime/Lua/LuaBind/LuaBindState.h | 43 +- Runtime/Lua/LuaBind/LuaBindUtility.h | 14 +- Runtime/Lua/LuaBind/LuaBindVM.cpp | 40 +- Runtime/Lua/LuaBind/LuaBindVM.h | 19 +- Runtime/Lua/LuaBind/signal/bind.h | 510 +++++++++++++++++++++ Runtime/Lua/LuaBind/signal/remove_from_container.h | 32 ++ Runtime/Lua/LuaBind/signal/signal.h | 451 ++++++++++++++++++ Runtime/Lua/LuaBind/signal/slot.h | 203 ++++++++ 17 files changed, 1388 insertions(+), 236 deletions(-) create mode 100644 Runtime/Lua/LuaBind/LuaBindHelper.cpp create mode 100644 Runtime/Lua/LuaBind/LuaBindHelper.h create mode 100644 Runtime/Lua/LuaBind/signal/bind.h create mode 100644 Runtime/Lua/LuaBind/signal/remove_from_container.h create mode 100644 Runtime/Lua/LuaBind/signal/signal.h create mode 100644 Runtime/Lua/LuaBind/signal/slot.h (limited to 'Runtime/Lua/LuaBind') diff --git a/Runtime/Lua/LuaBind/LuaBindClass.cpp b/Runtime/Lua/LuaBind/LuaBindClass.cpp index 7fd603c..9c67475 100644 --- a/Runtime/Lua/LuaBind/LuaBindClass.cpp +++ b/Runtime/Lua/LuaBind/LuaBindClass.cpp @@ -5,6 +5,8 @@ namespace LuaBind { + UIDGenerator gClassIDGenerator; + #if LUA_BIND_ENABLE_PLAIN_CLASS int PlainClass::registry(lua_State* L) diff --git a/Runtime/Lua/LuaBind/LuaBindClass.hpp b/Runtime/Lua/LuaBind/LuaBindClass.hpp index 154a4ce..f0fdf43 100644 --- a/Runtime/Lua/LuaBind/LuaBindClass.hpp +++ b/Runtime/Lua/LuaBind/LuaBindClass.hpp @@ -2,25 +2,24 @@ #define __LUA_BIND_CLASS_H__ #include "LuaBindConfig.h" - -#if LUA_BIND_PROFILER #include -#endif - +#include #include - #include "LuaBindRef.h" #include "LuaBindMemberRef.h" #include "LuaBindCFunctions.h" #include "LuaBindWatchDog.h" #include "LuaBindUtility.h" +#include "LuaBindHelper.h" namespace LuaBind { - class VM; - // +#define CLASS_NONE_ID (-1) + + extern UIDGenerator gClassIDGenerator; + // 虚基类,为了实现多态。需要访问下面这些接口的外部基类需要虚继承此类,之后再派生链中就会 // 调用对应实体的方法。注意继承此类时不能实现下面的方法,实现在NativeClass中,实现会 // 导致二义性。 @@ -28,24 +27,19 @@ namespace LuaBind // 依据Effective C++条款40,如果在必须使用virtual base基类情况下,应该尽可能避免向其中放 // 置数据成员,规避数据成员初始化造成的一些隐性问题。依据这一点,vpb基类更加接近C#和Java中 // 的Interface。所以,在这里把类用I开头标识这是一个接口。 - // class Object { public: Object() {}; virtual ~Object() {}; - // // 成员引用管理,在实例的ref table里。设置、取、清除。 - // virtual bool PushMemberRef(State& state, int refID) = 0; virtual bool PushUserdata(State& state) = 0; virtual bool PushMemberTable(State& state) = 0; virtual bool PushRefTable(State& state) = 0; - // // 被NativeClass实现。保持和释放native资源。 - // virtual void Retain() = 0; virtual void Release() = 0; @@ -56,43 +50,34 @@ namespace LuaBind //{ //} - // // 需要暴露给lua的native class需要继承此类。通过lua管理的实例要确保引用计数的正确性,在多个线程中需要确 // 定不会误释放。 - // template class NativeClass : public BASE { public: + enum NativeClassTableIndex { kRefTable = 1, kMemberTable = 2, kClassTable = 3 }; - // // 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。 // 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体, // 避免lua频繁的调用gc检测。 - // template void Retain(State& state, DATATYPE* userdata); - // // 对userdata减少一个引用在ref table里,以尝试回收userdata。 - // template void Release(State& state, DATATYPE* userdata); - // // 将userdata push到栈顶,如果没有初始化mUserdata,初始化设置好元表并把初始化好的 // userdata留在栈顶。并添加一个引用。这是一个将native对象所有权移交给lua控制的方法。 - // + bool PushUserdata(State& state) override; bool PushMemberRef(State& state, int refID) override; - bool PushUserdata(State& state) override; bool PushMemberTable(State& state) override; bool PushRefTable(State& state) override; - // // WatchDog添加一个native引用。luaVM引用不会提供外部接口。继承此类的派生类不能直接使用 // delete方法,应该使用Release释放。一般情况下这个操作由虚拟机__gc进行,但是允许用户 // 程序在native中隔绝虚拟机情况下释放,这种情况下要使用Release。 // // 这两个函数是native接口。 - // void Retain() override final; void Release() override final; @@ -103,12 +88,11 @@ namespace LuaBind protected: - NativeClass(); + // 需要指明对象所属的虚拟机 + NativeClass(LuaBind::VM* vm); virtual ~NativeClass(); - // // 成员引用管理,在实例的ref table里。设置、取、清除 - // void SetMemberRef(State& state, MemberRef& memRef, int idx); bool PushMemberRef(State& state, MemberRef& memRef); void ClearMemberRef(State& state, MemberRef& memRef); @@ -119,14 +103,11 @@ namespace LuaBind static void RegisterClassShared(State& state); static void RegisterFactoryClass(State& state); - static void RegisterSingletonClass(State& state); static void SetClassTableRef(State& state, int idx); static void PushClassTable(State& state); - // // 创建userdata,绑定实例到state。 - // void BindToLua(State& state); //------------------------------------------------------------------------------// @@ -149,25 +130,16 @@ namespace LuaBind //--------------------------------------------------------------------------------// - // - // class table,工厂和单例都有。 - // - static StrongRef mClassTable; + // 类型的全局UID,在不同的虚拟机中相同 + static int sClassID; - // - // 如果类是单例,这个用来保存singleton的引用关系,以保证不会被回收类似普通类的ref table。 - // 单例的成员是全生命周期的,所以直接在_LUA_BIND_STRONGREF_TABLE。单例对userdata进行 - // Retain\Release和member ref操作时和工厂实例不同,是存在下面这个ref table里 - // 的,这个table在_LUA_BIND_STRONGREF_TABLE里。 - // - static StrongRef mSingletonRefTable; + // 所属的虚拟机 + LuaBind::VM* mOwner; - // // 通过userdata可以拿到: // 1: ref table // 2: member table // 3: class table - // WeakRef mUserdata; // 通过后才能删除 @@ -204,10 +176,10 @@ namespace LuaBind #endif //--------------------------------------------------------------------------------// + template + int NativeClass::sClassID = CLASS_NONE_ID; - // // 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 - // template int NativeClass::_GetClassName(lua_State* L) { @@ -220,9 +192,7 @@ namespace LuaBind //--------------------------------------------------------------------------------// - // // 注册工厂和单例共有的类成员 - // template void NativeClass::RegisterClassShared(State& state) { @@ -235,9 +205,7 @@ namespace LuaBind state.RegisterMethods(regTable); } - // // 工厂类的成员,注册在class table - // template void NativeClass::RegisterFactoryClass(State& state) { @@ -249,36 +217,27 @@ namespace LuaBind state.RegisterMethods(regTable); } - // - // 单例类的成员,注册在class table - // template - void NativeClass::RegisterSingletonClass(State& state) + void NativeClass::SetClassTableRef(State& state, int idx) { - luaL_Reg regTable[] = { - { NULL, NULL } - }; - - state.RegisterMethods(regTable); + if (sClassID == CLASS_NONE_ID) + sClassID = gClassIDGenerator.GetID(); + LuaBind::VM* vm = state.GetVM(); + vm->RegisterClassI(state, sClassID, idx); } template void NativeClass::PushClassTable(State& state) { - assert(mClassTable); - - mClassTable.PushRef(state); + LuaBind::VM* vm = state.GetVM(); + vm->PushClassTable(state, sClassID); } template - void NativeClass::SetClassTableRef(State& state, int idx) - { - mClassTable.SetRef(state, idx); - } - - template - NativeClass::NativeClass() + NativeClass::NativeClass(LuaBind::VM* vm) : mWatchDog() + , mUserdata(vm) + , mOwner(vm) #if LUA_BIND_PROFILER , mSafer(false) #endif @@ -380,8 +339,7 @@ namespace LuaBind template bool NativeClass::PushUserdata(State& state) { - assert(!TYPE::IsClassSingleton()); - if (!mUserdata) + if (!mUserdata) // 第一次创建 { BindToLua(state); return true; @@ -413,28 +371,12 @@ namespace LuaBind template bool NativeClass::PushRefTable(State& state) { - // Singleton - if (TYPE::IsClassSingleton()) - { - if (!this->mSingletonRefTable) { - lua_newtable(state); - this->mSingletonRefTable.SetRef(state, -1); // strong ref to member table won't be garbage collected - } - else { - this->mSingletonRefTable.PushRef(state); - } - return true; - } - // Factory - else + if (this->PushUserdata(state)) { - if (this->PushUserdata(state)) + if (lua_getmetatable(state, -1)) // RefTable { - if (lua_getmetatable(state, -1)) - { - lua_replace(state, -2); - return true; - } + lua_replace(state, -2); + return true; } } return false; @@ -450,8 +392,6 @@ namespace LuaBind template void NativeClass::BindToLua(State& state) { - // 单例不能绑定userdata - assert(!TYPE::IsClassSingleton()); assert(!mUserdata); // 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。 @@ -465,10 +405,10 @@ namespace LuaBind PushClassTable(state); // class table // stack: - // -1: class table - // -2: member table - // -3: ref table - // -4: userdata + // -1 class table + // -2 member table + // -3 ref table + // -4 userdata int top = state.GetTop(); int memberTable = top - 1; @@ -488,10 +428,10 @@ namespace LuaBind lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__newindex"); - // 设置元表 - lua_setmetatable(state, -2); // class is meta of member - lua_setmetatable(state, -2); // member is meta of ref - lua_setmetatable(state, -2); // ref is meta of userdata + // 设置元表 userdata -> refTable -> memberTable -> classTable + lua_setmetatable(state, -2); // class is metatable of member + lua_setmetatable(state, -2); // member is metatable of ref + lua_setmetatable(state, -2); // ref is metatable of userdata // 设置一个userdata的弱引用,方便通过PushLuaUserdata方法返回lua对象 mUserdata.SetRef(state, -1); @@ -504,9 +444,7 @@ namespace LuaBind #endif } - // // 成员引用管理 - // template void NativeClass::SetMemberRef(State& state, MemberRef& memRef, int idx) { @@ -810,10 +748,7 @@ namespace LuaBind int NativeClass::_GetClass(lua_State* L) { LUA_BIND_STATE(L); - if (!mClassTable) - lua_pushnil(L); - else - mClassTable.PushRef(state); + state.GetVM()->PushClassTable(state, sClassID); return 1; } @@ -828,11 +763,6 @@ namespace LuaBind return 1; } - template StrongRef NativeClass::mClassTable; // class table - template StrongRef NativeClass::mSingletonRefTable; // 单例 - - - } #endif \ No newline at end of file diff --git a/Runtime/Lua/LuaBind/LuaBindHelper.cpp b/Runtime/Lua/LuaBind/LuaBindHelper.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Runtime/Lua/LuaBind/LuaBindHelper.h b/Runtime/Lua/LuaBind/LuaBindHelper.h new file mode 100644 index 0000000..f095add --- /dev/null +++ b/Runtime/Lua/LuaBind/LuaBindHelper.h @@ -0,0 +1,16 @@ +#ifndef _LUA_BIND_HELPER_H +#define _LUA_BIND_HELPER_H + +namespace LuaBind +{ + class UIDGenerator + { + public: + UIDGenerator() { m_Cur = 0; } + int GetID() { return ++m_Cur; } + + private: + int m_Cur; + }; +}; +#endif \ No newline at end of file diff --git a/Runtime/Lua/LuaBind/LuaBindMemberRef.h b/Runtime/Lua/LuaBind/LuaBindMemberRef.h index 045d6ef..ecc50f5 100644 --- a/Runtime/Lua/LuaBind/LuaBindMemberRef.h +++ b/Runtime/Lua/LuaBind/LuaBindMemberRef.h @@ -6,10 +6,8 @@ namespace LuaBind { - // // 实例的ref table保存的member ref。由luax class做具体的管理。实例的ref table是强引用,用来管理里面member的生命周期。 // 用来在lua和native之间进行数据沟通。 - // class MemberRef { public: diff --git a/Runtime/Lua/LuaBind/LuaBindRef.cpp b/Runtime/Lua/LuaBind/LuaBindRef.cpp index 676525a..b2f8e1c 100644 --- a/Runtime/Lua/LuaBind/LuaBindRef.cpp +++ b/Runtime/Lua/LuaBind/LuaBindRef.cpp @@ -4,16 +4,16 @@ namespace LuaBind { - Ref::Ref(RefMode mode) + Ref::Ref(LuaBind::VM* vm, RefMode mode) : mRefID(LUA_NOREF) , mMode(mode) + , mOwner(vm) { } Ref::~Ref() { // 自动释放引用 - } Ref::operator bool() @@ -21,11 +21,49 @@ namespace LuaBind return (mRefID != LUA_NOREF); } - bool Ref::PushRef(State& state) + void Ref::UnRef() + { + if (mRefID == LUA_NOREF) + return; + VM* vm = mOwner; + if (!vm) return; + if (mMode == STRONG_REF) + { + RefTable& table = vm->GetStrongRefTable(); + table.UnRef(mRefID); + mRefID = LUA_NOREF; + } + else if (mMode == WEAK_REF) + { + RefTable& table = vm->GetWeakRefTable(); + table.UnRef(mRefID); + mRefID = LUA_NOREF; + } + } + + void Ref::SetRef(LuaBind::State& state, int idx) + { + assert(state.GetVM() == mOwner); + + VM* vm = mOwner; + if (!vm) return; + if (mMode == STRONG_REF) + { + RefTable& table = vm->GetStrongRefTable(); + mRefID = table.Ref(state, idx); + } + else if (mMode == WEAK_REF) + { + RefTable& table = vm->GetWeakRefTable(); + mRefID = table.Ref(state, idx); + } + } + + bool Ref::PushRef(LuaBind::State& state) { assert(mRefID != LUA_NOREF); - VM* vm = state.GetVM(); + VM* vm = mOwner; if (!vm) return false; if (mMode == STRONG_REF) { @@ -39,35 +77,19 @@ namespace LuaBind } else { - state.PushNil(); + state.PushNil(); return false; } return true; } - void Ref::SetRef(State& state, int idx) - { - VM* vm = state.GetVM(); - if (!vm) return; - if (mMode == STRONG_REF) - { - RefTable& table = vm->GetStrongRefTable(); - mRefID = table.Ref(state, idx); - } - else if (mMode == WEAK_REF) - { - RefTable& table = vm->GetWeakRefTable(); - mRefID = table.Ref(state, idx); - } - } - - StrongRef::StrongRef() - : Ref(STRONG_REF) + StrongRef::StrongRef(LuaBind::VM* vm) + : Ref(vm, STRONG_REF) { } - WeakRef::WeakRef() - : Ref(WEAK_REF) + WeakRef::WeakRef(LuaBind::VM* vm) + : Ref(vm, WEAK_REF) { } diff --git a/Runtime/Lua/LuaBind/LuaBindRef.h b/Runtime/Lua/LuaBind/LuaBindRef.h index 7058094..cd2fad1 100644 --- a/Runtime/Lua/LuaBind/LuaBindRef.h +++ b/Runtime/Lua/LuaBind/LuaBindRef.h @@ -11,40 +11,41 @@ namespace LuaBind class Ref { public: - enum RefMode { STRONG_REF, WEAK_REF }; - Ref(RefMode mode = STRONG_REF); + Ref(LuaBind::VM* vm, RefMode mode = STRONG_REF); virtual ~Ref(); operator bool(); // 将栈上的对象添加到全局引用表中 - void SetRef(State& state, int idx); + void SetRef(LuaBind::State& state, int idx); + + // 解除引用 + void UnRef(); // 将引用的对象压入栈 - bool PushRef(State& state); + bool PushRef(LuaBind::State& state); int GetRefID() { return mRefID; } RefMode GetRefMode() { return mMode; } private: - - int mRefID; - RefMode mMode; - + LuaBind::VM* mOwner; // 所属的虚拟机 + RefMode mMode; // 模式 + int mRefID; // 引用ID }; // 强引用,在LUA_REGISTRYINDEX["GAMELAB_UNIVERSAL_STRONG_REFERENCE_TABLE"]里,保证lua object不会被回收 class StrongRef: public Ref { public: - StrongRef(); + StrongRef(LuaBind::VM* vm); }; @@ -52,7 +53,7 @@ namespace LuaBind class WeakRef : public Ref { public: - WeakRef(); + WeakRef(LuaBind::VM* vm); }; diff --git a/Runtime/Lua/LuaBind/LuaBindRefTable.cpp b/Runtime/Lua/LuaBind/LuaBindRefTable.cpp index 39ef9ab..f8a7a78 100644 --- a/Runtime/Lua/LuaBind/LuaBindRefTable.cpp +++ b/Runtime/Lua/LuaBind/LuaBindRefTable.cpp @@ -1,11 +1,12 @@ #include "LuaBindRefTable.h" #include "LuaBindState.h" +#include "LuaBindVM.h" namespace LuaBind { - RefTable::RefTable() - : mState(nullptr) + RefTable::RefTable(LuaBind::VM* vm) + : mVM(vm) { } @@ -13,9 +14,9 @@ namespace LuaBind { } - void RefTable::Init(State& state, cc8* name, cc8* mode) + void RefTable::Init( cc8* name, cc8* mode) { - assert(!mState); + assert(mVM); assert(name); mName = name; @@ -25,7 +26,7 @@ namespace LuaBind if (mode[i] == 'k') mMode |= WEAK_KEY; else if (mode[i] == 'v') mMode |= WEAK_VALUE; } - mState = state.GetHandle(); + State state = mVM->GetMainState(); state.GetField(LUA_REGISTRYINDEX, name); // register[mName] if (state.IsNil(-1)) @@ -58,21 +59,22 @@ namespace LuaBind bool RefTable::IsKeyWeak() { - assert(mState); + assert(mVM); return mMode & WEAK_KEY; } bool RefTable::IsValueWeak() { - assert(mState); + assert(mVM); return mMode & WEAK_VALUE; } int RefTable::Ref(State& state, int idx) { - assert(mState); + assert(mVM); + assert(mVM == state.GetVM()); idx = state.AbsIndex(idx); state.GetField(LUA_REGISTRYINDEX, mName); // ref table @@ -83,10 +85,11 @@ namespace LuaBind return refID; } - void RefTable::Unref(State& state, int refID) + void RefTable::UnRef(int refID) { - assert(mState); + assert(mVM); + State state = mVM->GetMainState(); state.GetField(LUA_REGISTRYINDEX, mName); // ref table luaL_unref(state, -1, refID); state.Pop(); @@ -95,24 +98,27 @@ namespace LuaBind void RefTable::PushRefTable(State& state) { - assert(mState); + assert(mVM); + assert(mVM == state.GetVM()); lua_getfield(state, LUA_REGISTRYINDEX, mName); } void RefTable::PushRef(State& state, int refID) { - assert(mState); + assert(mVM); + assert(mVM == state.GetVM()); lua_getfield(state, LUA_REGISTRYINDEX, mName); lua_rawgeti(state, -1, refID); lua_replace(state, -2); } - void RefTable::Clear(State& state) + void RefTable::Clear() { - assert(mState); + assert(mVM); + State state = mVM->GetMainState(); lua_newtable(state); state.SetField(LUA_REGISTRYINDEX, mName); } diff --git a/Runtime/Lua/LuaBind/LuaBindRefTable.h b/Runtime/Lua/LuaBind/LuaBindRefTable.h index 3401a53..d3de7d6 100644 --- a/Runtime/Lua/LuaBind/LuaBindRefTable.h +++ b/Runtime/Lua/LuaBind/LuaBindRefTable.h @@ -7,8 +7,10 @@ namespace LuaBind { class State; + class VM; // ref table 管理,对strong ref table和weak ref table两个table的代理。 + // 保存在global_State.l_registry,所以是虚拟机下的所有协程共享的 class RefTable { public: @@ -19,19 +21,19 @@ namespace LuaBind WEAK_VALUE = 1 << 1 }; - RefTable(); + RefTable(LuaBind::VM* vm); ~RefTable(); - inline operator bool() { return mState; }; + inline operator bool() { return mVM; }; - void Init(State& state, cc8* name, cc8* mode = nullptr); + void Init(cc8* name, cc8* mode = nullptr); bool IsKeyWeak(); bool IsValueWeak(); // 对stack[idx]的实体在此ref table中增加一个引用,并返回refID int Ref(State& state, int idx); - void Unref(State& state, int refID); + void UnRef(int refID); // 将此 ref table 放在栈顶 void PushRefTable(State& state); @@ -40,13 +42,14 @@ namespace LuaBind void PushRef(State& state, int refID); // 清空 ref table,表还留在LUA_REGISTRYINDEX[mName] - void Clear(State& state); + void Clear(); private: + friend class VM; friend class State; - lua_State* mState; // 用来做一些确认工作 + VM* mVM; // 所属的虚拟机 cc8* mName; // ref table的名称 int mMode; // ref table的类型 diff --git a/Runtime/Lua/LuaBind/LuaBindState.h b/Runtime/Lua/LuaBind/LuaBindState.h index 9028583..e5b8f6c 100644 --- a/Runtime/Lua/LuaBind/LuaBindState.h +++ b/Runtime/Lua/LuaBind/LuaBindState.h @@ -27,6 +27,7 @@ namespace LuaBind // userdata // 从userdata通过getmetatable获取上级metatable。除此之外还有一个class table注册在对应 // 的名称空间里。 + // 把LuaState理解成执行栈 LUA_BIND_API class State { public: @@ -151,9 +152,6 @@ namespace LuaBind // 注册工厂,适用于普通类,有New方法 template void RegisterFactory(); - // 注册单例,没有New方法 - template void RegisterSingleton(); - // 注册枚举 void RegisterEnum(cc8* name, Enum* enums); @@ -315,44 +313,7 @@ namespace LuaBind TYPE::SetClassTableRef(state, -1); - SetField(top, type); - - // reset top - lua_settop(L, top); - - // 后处理 - TYPE::RegisterPostprocess(state); - } - - // 注册单例 - template - void State::RegisterSingleton() - { - lua_State* L = mState; - State& state = *this; - - int top = lua_gettop(L); // namespace table - assert(lua_istable(L, top)); - - // class table. - lua_newtable(L); - TYPE::RegisterClassShared(state); - TYPE::RegisterSingletonClass(state); - TYPE::RegisterClass(state); - - TYPE::SetClassTableRef(state, -1); - - lua_pushvalue(state, -1); - lua_setfield(state, -2, "__index"); - -#if LUA_BIND_ENABLE_NATIVE_EXTEND - // .Extend() - lua_pushvalue(state, -1); // class table - lua_pushcclosure(state, TYPE::_ExtendSingleton, 1); - lua_setfield(state, -2, "Extend"); -#endif - - cc8* type = TYPE::GetSingletonName(); + // namespace[type] = class SetField(top, type); // reset top diff --git a/Runtime/Lua/LuaBind/LuaBindUtility.h b/Runtime/Lua/LuaBind/LuaBindUtility.h index ffc5099..fd39f47 100644 --- a/Runtime/Lua/LuaBind/LuaBindUtility.h +++ b/Runtime/Lua/LuaBind/LuaBindUtility.h @@ -11,24 +11,13 @@ static void RegisterClass(::State&); \ static void RegisterPostprocess(::State&); \ static const char* GetFactoryName() { return #type; };\ - static const char* GetClassName() { return #type; };\ - static bool IsClassSingleton() { return false; } + static const char* GetClassName() { return #type; }; // 作为基类的抽象工厂类可以使用此宏,注册一个入口,在派生类的注册函数中调用,注册基类的这些方法。 #define LUA_BIND_DECL_ABSTRACT_FACTORY() \ static void RegisterClass(::State&);\ static void RegisterPostprocess(::State&) -// RegisterClass 注册类的方法和成员,比如枚举、常量等到class table GetSingletonName 获得单例的类名 -#define LUA_BIND_DECL_SINGLETON(type, ...) \ - friend class ::State; \ - friend class ::NativeClass; \ - static void RegisterClass(::State&); \ - static void RegisterPostprocess(::State&); \ - static const char* GetSingletonName() { return #type; }; \ - static const char* GetClassName() { return #type; }; \ - static bool IsClassSingleton() { return true; } - #define LUA_BIND_DECL_METHOD(mtd) static int mtd(lua_State* L) #define LUA_BIND_DECL_ENUM(e, under_line_index) @@ -42,7 +31,6 @@ // 用来注册的宏。之前这里忘了用可变宏,导致没有luaclastable ref没有注册对。 #define LUA_BIND_REGISTER_FACTORY(state, param) state.RegisterFactory() -#define LUA_BIND_REGISTER_SINGLETON(state, param) state.RegisterSingleton() #define LUA_BIND_REGISTER_ABSTRACT_FACTORY(state, type) type::RegisterPostprocess(state) #define LUA_BIND_REGISTER_METHODS(state, ...) \ do{ \ diff --git a/Runtime/Lua/LuaBind/LuaBindVM.cpp b/Runtime/Lua/LuaBind/LuaBindVM.cpp index 268a5ed..6b39288 100644 --- a/Runtime/Lua/LuaBind/LuaBindVM.cpp +++ b/Runtime/Lua/LuaBind/LuaBindVM.cpp @@ -3,8 +3,10 @@ namespace LuaBind { + static cc8* kStrongTableName = "GAMELAB_UNIVERSAL_STRONG_REFERENCE_TABLE"; + static cc8* kWeakTableName = "GAMELAB_UNIVERSAL_WEAK_REFERENCE_TABLE"; - VM::VMap VM::VMs; // 通过线程查找虚拟机,为了方便 + std::map VM::VMs; // 通过线程查找虚拟机,为了方便 VM* VM::TryGetVM(global_State* gState) { @@ -12,7 +14,7 @@ namespace LuaBind if (it != VMs.end()) return it->second; else - return nullptr; + return NULL; } VM* VM::TryGetVM(lua_State* state) @@ -21,11 +23,11 @@ namespace LuaBind } VM::VM() - : mStrongRefTable() - , mWeakRefTable() + : mStrongRefTable(this) + , mWeakRefTable(this) + , mClasses() { mMainThread = luaL_newstate(); - assert(mMainThread); mGlobalState = G(mMainThread); VMs.insert(std::pair(mGlobalState, this)); @@ -42,8 +44,8 @@ namespace LuaBind { LUA_BIND_STATE(mMainThread); - mStrongRefTable.Init(state, "GAMELAB_UNIVERSAL_STRONG_REFERENCE_TABLE"); - mWeakRefTable.Init(state, "GAMELAB_UNIVERSAL_WEAK_REFERENCE_TABLE", "v"); + mStrongRefTable.Init(kStrongTableName); + mWeakRefTable.Init(kWeakTableName, "v"); } lua_State* VM::CreateThread() @@ -79,4 +81,28 @@ namespace LuaBind luaL_openlibs(mMainThread); } + int VM::RegisterClassI(State& state, int classID, int index) + { + assert(state.GetVM() == this); + assert(mClasses.count(classID) == 0); + StrongRef ref = StrongRef(this); + ref.SetRef(state, index); + auto cls = std::pair(classID, ref); + mClasses.insert(cls); + return 1; + } + + void VM::PushClassTable(State& state, int classID) + { + assert(state.GetVM() == this); + auto ref = mClasses.find(classID); + if (ref == mClasses.end()) + { + state.PushNil(); + return; + } + StrongRef cls = ref->second; + cls.PushRef(state); + } + } \ No newline at end of file diff --git a/Runtime/Lua/LuaBind/LuaBindVM.h b/Runtime/Lua/LuaBind/LuaBindVM.h index 3bfe899..37810b9 100644 --- a/Runtime/Lua/LuaBind/LuaBindVM.h +++ b/Runtime/Lua/LuaBind/LuaBindVM.h @@ -3,6 +3,7 @@ #include #include +#include #include "LuaBindRef.h" #include "LuaBindConfig.h" @@ -32,20 +33,22 @@ namespace LuaBind lua_State* CreateThread(); State GetMainState(); - RefTable& GetStrongRefTable(); + RefTable& GetStrongRefTable(); RefTable& GetWeakRefTable(); - private: + int RegisterClassI(State& state, int classID, int index); + void PushClassTable(State& state, int classID); - typedef std::map VMap; + private: + static std::map VMs; // 通过global_State索引虚拟机,为了方便 - static VMap VMs; // 通过global_State索引虚拟机,为了方便 + global_State* mGlobalState; // 虚拟机的global_State,由当前虚拟机的所有线程共享,保存注册表、管理GC + lua_State* mMainThread; // 主线程 - RefTable mStrongRefTable; // GAMELAB_UNIVERSAL_STRONG_REFERENCE_TABLE - RefTable mWeakRefTable; // GAMELAB_UNIVERSAL_WEAK_REFERENCE_TABLE + RefTable mStrongRefTable; // 全局强引用表 + RefTable mWeakRefTable; // 全局弱引用表 - global_State* mGlobalState; // 虚拟机的global_State,由当前虚拟机的所有线程共享 - lua_State* mMainThread; // 主线程 + std::unordered_map mClasses; // 类型 #if LUA_BIND_PROFILER size_t mObjectCount; // 统计所有在此虚拟机中创建的实例 diff --git a/Runtime/Lua/LuaBind/signal/bind.h b/Runtime/Lua/LuaBind/signal/bind.h new file mode 100644 index 0000000..e29896b --- /dev/null +++ b/Runtime/Lua/LuaBind/signal/bind.h @@ -0,0 +1,510 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef BASE_BIND_H_INCLUDED +#define BASE_BIND_H_INCLUDED +#pragma once + +// BindAdapter0_fun +template +class BindAdapter0_fun +{ + F f; +public: + BindAdapter0_fun(const F& f) : f(f) { } + + R operator()() { return f(); } + + template + R operator()(const A1& a1) { return f(); } + + template + R operator()(const A1& a1, const A2& a2) { return f(); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(); } +}; + +template +class BindAdapter0_fun +{ + F f; +public: + BindAdapter0_fun(const F& f) : f(f) { } + + void operator()() { f(); } + + template + void operator()(const A1& a1) { f(); } + + template + void operator()(const A1& a1, const A2& a2) { f(); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(); } +}; + +template +BindAdapter0_fun +Bind(const F& f) +{ + return BindAdapter0_fun(f); +} + +// BindAdapter0_mem +template +class BindAdapter0_mem +{ + R (T::*m)(); + T* t; +public: + template + BindAdapter0_mem(R (T::*m)(), T2* t) : m(m), t(t) { } + + R operator()() { return (t->*m)(); } + + template + R operator()(const A1& a1) { return (t->*m)(); } + + template + R operator()(const A1& a1, const A2& a2) { return (t->*m)(); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(); } +}; + +template +class BindAdapter0_mem +{ + void (T::*m)(); + T* t; +public: + template + BindAdapter0_mem(void (T::*m)(), T2* t) : m(m), t(t) { } + + void operator()() { (t->*m)(); } + + template + void operator()(const A1& a1) { (t->*m)(); } + + template + void operator()(const A1& a1, const A2& a2) { (t->*m)(); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(); } +}; + +template +BindAdapter0_mem +Bind(R (T::*m)(), T2* t) +{ + return BindAdapter0_mem(m, t); +} + +// BindAdapter1_fun +template +class BindAdapter1_fun +{ + F f; + X1 x1; +public: + BindAdapter1_fun(const F& f, X1 x1) : f(f), x1(x1) { } + + R operator()() { return f(x1); } + + template + R operator()(const A1& a1) { return f(x1); } + + template + R operator()(const A1& a1, const A2& a2) { return f(x1); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1); } +}; + +template +class BindAdapter1_fun +{ + F f; + X1 x1; +public: + BindAdapter1_fun(const F& f, X1 x1) : f(f), x1(x1) { } + + void operator()() { f(x1); } + + template + void operator()(const A1& a1) { f(x1); } + + template + void operator()(const A1& a1, const A2& a2) { f(x1); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1); } +}; + +template +BindAdapter1_fun +Bind(const F& f, X1 x1) +{ + return BindAdapter1_fun(f, x1); +} + +// BindAdapter1_mem +template +class BindAdapter1_mem +{ + R (T::*m)(B1); + T* t; + X1 x1; +public: + template + BindAdapter1_mem(R (T::*m)(B1), T2* t, X1 x1) : m(m), t(t), x1(x1) { } + + R operator()() { return (t->*m)(x1); } + + template + R operator()(const A1& a1) { return (t->*m)(x1); } + + template + R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1); } +}; + +template +class BindAdapter1_mem +{ + void (T::*m)(B1); + T* t; + X1 x1; +public: + template + BindAdapter1_mem(void (T::*m)(B1), T2* t, X1 x1) : m(m), t(t), x1(x1) { } + + void operator()() { (t->*m)(x1); } + + template + void operator()(const A1& a1) { (t->*m)(x1); } + + template + void operator()(const A1& a1, const A2& a2) { (t->*m)(x1); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1); } +}; + +template +BindAdapter1_mem +Bind(R (T::*m)(B1), T2* t, X1 x1) +{ + return BindAdapter1_mem(m, t, x1); +} + +// BindAdapter2_fun +template +class BindAdapter2_fun +{ + F f; + X1 x1; + X2 x2; +public: + BindAdapter2_fun(const F& f, X1 x1, X2 x2) : f(f), x1(x1), x2(x2) { } + + R operator()() { return f(x1, x2); } + + template + R operator()(const A1& a1) { return f(x1, x2); } + + template + R operator()(const A1& a1, const A2& a2) { return f(x1, x2); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2); } +}; + +template +class BindAdapter2_fun +{ + F f; + X1 x1; + X2 x2; +public: + BindAdapter2_fun(const F& f, X1 x1, X2 x2) : f(f), x1(x1), x2(x2) { } + + void operator()() { f(x1, x2); } + + template + void operator()(const A1& a1) { f(x1, x2); } + + template + void operator()(const A1& a1, const A2& a2) { f(x1, x2); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2); } +}; + +template +BindAdapter2_fun +Bind(const F& f, X1 x1, X2 x2) +{ + return BindAdapter2_fun(f, x1, x2); +} + +// BindAdapter2_mem +template +class BindAdapter2_mem +{ + R (T::*m)(B1, B2); + T* t; + X1 x1; + X2 x2; +public: + template + BindAdapter2_mem(R (T::*m)(B1, B2), T2* t, X1 x1, X2 x2) : m(m), t(t), x1(x1), x2(x2) { } + + R operator()() { return (t->*m)(x1, x2); } + + template + R operator()(const A1& a1) { return (t->*m)(x1, x2); } + + template + R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2); } +}; + +template +class BindAdapter2_mem +{ + void (T::*m)(B1, B2); + T* t; + X1 x1; + X2 x2; +public: + template + BindAdapter2_mem(void (T::*m)(B1, B2), T2* t, X1 x1, X2 x2) : m(m), t(t), x1(x1), x2(x2) { } + + void operator()() { (t->*m)(x1, x2); } + + template + void operator()(const A1& a1) { (t->*m)(x1, x2); } + + template + void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2); } +}; + +template +BindAdapter2_mem +Bind(R (T::*m)(B1, B2), T2* t, X1 x1, X2 x2) +{ + return BindAdapter2_mem(m, t, x1, x2); +} + +// BindAdapter3_fun +template +class BindAdapter3_fun +{ + F f; + X1 x1; + X2 x2; + X3 x3; +public: + BindAdapter3_fun(const F& f, X1 x1, X2 x2, X3 x3) : f(f), x1(x1), x2(x2), x3(x3) { } + + R operator()() { return f(x1, x2, x3); } + + template + R operator()(const A1& a1) { return f(x1, x2, x3); } + + template + R operator()(const A1& a1, const A2& a2) { return f(x1, x2, x3); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2, x3); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2, x3); } +}; + +template +class BindAdapter3_fun +{ + F f; + X1 x1; + X2 x2; + X3 x3; +public: + BindAdapter3_fun(const F& f, X1 x1, X2 x2, X3 x3) : f(f), x1(x1), x2(x2), x3(x3) { } + + void operator()() { f(x1, x2, x3); } + + template + void operator()(const A1& a1) { f(x1, x2, x3); } + + template + void operator()(const A1& a1, const A2& a2) { f(x1, x2, x3); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2, x3); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2, x3); } +}; + +template +BindAdapter3_fun +Bind(const F& f, X1 x1, X2 x2, X3 x3) +{ + return BindAdapter3_fun(f, x1, x2, x3); +} + +// BindAdapter3_mem +template +class BindAdapter3_mem +{ + R (T::*m)(B1, B2, B3); + T* t; + X1 x1; + X2 x2; + X3 x3; +public: + template + BindAdapter3_mem(R (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2, X3 x3) : m(m), t(t), x1(x1), x2(x2), x3(x3) { } + + R operator()() { return (t->*m)(x1, x2, x3); } + + template + R operator()(const A1& a1) { return (t->*m)(x1, x2, x3); } + + template + R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2, x3); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2, x3); } + + template + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2, x3); } +}; + +template +class BindAdapter3_mem +{ + void (T::*m)(B1, B2, B3); + T* t; + X1 x1; + X2 x2; + X3 x3; +public: + template + BindAdapter3_mem(void (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2) : m(m), t(t), x1(x1), x2(x2) { } + + void operator()() { (t->*m)(x1, x2, x3); } + + template + void operator()(const A1& a1) { (t->*m)(x1, x2, x3); } + + template + void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2, x3); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2, x3); } + + template + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2, x3); } +}; + +template +BindAdapter3_mem +Bind(R (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2) +{ + return BindAdapter3_mem(m, t, x1, x2); +} + +// Helper class to holds references as pointers (to avoid copying the +// original object). +template +class RefWrapper +{ + T* ptr; +public: + RefWrapper(T& ref) : ptr(&ref) { } + operator T&() const { return *ptr; } +}; + +// Creates RefWrappers, useful to wrap arguments that have to be +// passed as a reference when you use Bind. +template +RefWrapper Ref(T& ref) +{ + return RefWrapper(ref); +} + +#endif diff --git a/Runtime/Lua/LuaBind/signal/remove_from_container.h b/Runtime/Lua/LuaBind/signal/remove_from_container.h new file mode 100644 index 0000000..9fdc442 --- /dev/null +++ b/Runtime/Lua/LuaBind/signal/remove_from_container.h @@ -0,0 +1,32 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef BASE_REMOVE_FROM_CONTAINER_H_INCLUDED +#define BASE_REMOVE_FROM_CONTAINER_H_INCLUDED +#pragma once + +namespace base { + +// Removes all ocurrences of the specified element from the STL container. +template +void remove_from_container(ContainerType& container, + typename ContainerType::const_reference element) +{ + for (typename ContainerType::iterator + it = container.begin(), + end = container.end(); it != end; ) { + if (*it == element) { + it = container.erase(it); + end = container.end(); + } + else + ++it; + } +} + +} + +#endif diff --git a/Runtime/Lua/LuaBind/signal/signal.h b/Runtime/Lua/LuaBind/signal/signal.h new file mode 100644 index 0000000..97882c6 --- /dev/null +++ b/Runtime/Lua/LuaBind/signal/signal.h @@ -0,0 +1,451 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef BASE_SIGNAL_H_INCLUDED +#define BASE_SIGNAL_H_INCLUDED +#pragma once + +//#include "base/slot.h" +//#include "base/remove_from_container.h" + +#include "./slot.h" +#include "./remove_from_container.h" + +#include + +// Signal0_base - Base class to delegate responsibility to +// functions of zero arguments. +template +class Signal0_base +{ +public: + typedef R ReturnType; + typedef Slot0 SlotType; + typedef std::vector SlotList; + +protected: + SlotList m_slots; + +public: + Signal0_base() { } + Signal0_base(const Signal0_base& s) + { + copy(s); + } + ~Signal0_base() + { + disconnectAll(); + } + + SlotType* addSlot(SlotType* slot) + { + m_slots.push_back(slot); + return slot; + } + + template + SlotType* connect(const F& f) + { + return addSlot(new Slot0_fun(f)); + } + + template + SlotType* connect(R (T::*m)(), T* t) + { + return addSlot(new Slot0_mem(m, t)); + } + + const SlotList& getSlots() const + { + return m_slots; + } + + void disconnect(SlotType* slot) + { + base::remove_from_container(m_slots, slot); + } + + void disconnectAll() + { + typename SlotList::iterator end = m_slots.end(); + for (typename SlotList::iterator + it = m_slots.begin(); it != end; ++it) + delete *it; + m_slots.clear(); + } + + bool empty() const + { + return m_slots.empty(); + } + + Signal0_base& operator=(const Signal0_base& s) { + copy(s); + return *this; + } + +private: + + void copy(const Signal0_base& s) + { + typename SlotList::const_iterator end = s.m_slots.end(); + for (typename SlotList::const_iterator + it = s.m_slots.begin(); it != end; ++it) { + m_slots.push_back((*it)->clone()); + } + } + +}; + +// Signal0 +template +class Signal0 : public Signal0_base +{ +public: + Signal0() { } + + Signal0(const Signal0& s) + : Signal0_base(s) { } + + R operator()(R default_result = R()) + { + R result(default_result); + typename Signal0_base::SlotList::iterator end = Signal0_base::m_slots.end(); + for (typename Signal0_base::SlotList::iterator + it = Signal0_base::m_slots.begin(); it != end; ++it) { + typename Signal0_base::SlotType* slot = *it; + result = (*slot)(); + } + return result; + } + + template + R operator()(R default_result, const Merger& m) + { + R result(default_result); + Merger merger(m); + typename Signal0_base::SlotList::iterator end = Signal0_base::m_slots.end(); + for (typename Signal0_base::SlotList::iterator + it = Signal0_base::m_slots.begin(); it != end; ++it) { + typename Signal0_base::SlotType* slot = *it; + result = merger(result, (*slot)()); + } + return result; + } + +}; + +// Signal0 +template<> +class Signal0 : public Signal0_base +{ +public: + Signal0() { } + + Signal0(const Signal0& s) + : Signal0_base(s) { } + + void operator()() + { + SlotList::iterator end = m_slots.end(); + for (SlotList::iterator + it = m_slots.begin(); it != end; ++it) { + SlotType* slot = *it; + (*slot)(); + } + } + +}; + +// Signal1_base - Base class to delegate responsibility to +// functions of one argument. +template +class Signal1_base +{ +public: + typedef R ReturnType; + typedef Slot1 SlotType; + typedef std::vector SlotList; + +protected: + SlotList m_slots; + +public: + Signal1_base() { } + Signal1_base(const Signal1_base& s) + { + copy(s); + } + ~Signal1_base() + { + disconnectAll(); + } + + SlotType* addSlot(SlotType* slot) + { + m_slots.push_back(slot); + return slot; + } + + template + SlotType* connect(const F& f) + { + return addSlot(new Slot1_fun(f)); + } + + template + SlotType* connect(R (T::*m)(A1), T* t) + { + return addSlot(new Slot1_mem(m, t)); + } + + const SlotList& getSlots() const + { + return m_slots; + } + + void disconnect(SlotType* slot) + { + base::remove_from_container(m_slots, slot); + } + + void disconnectAll() + { + typename SlotList::iterator end = m_slots.end(); + for (typename SlotList::iterator + it = m_slots.begin(); it != end; ++it) + delete *it; + m_slots.clear(); + } + + bool empty() const + { + return m_slots.empty(); + } + + Signal1_base& operator=(const Signal1_base& s) { + copy(s); + return *this; + } + +private: + + void copy(const Signal1_base& s) + { + typename SlotList::const_iterator end = s.m_slots.end(); + for (typename SlotList::const_iterator + it = s.m_slots.begin(); it != end; ++it) { + m_slots.push_back((*it)->clone()); + } + } + +}; + +// Signal1 +template +class Signal1 : public Signal1_base +{ +public: + Signal1() { } + + Signal1(const Signal1& s) + : Signal1_base(s) { } + + R operator()(A1 a1, R default_result = R()) + { + R result(default_result); + typename Signal1_base::SlotList::iterator end = Signal1_base::m_slots.end(); + for (typename Signal1_base::SlotList::iterator + it = Signal1_base::m_slots.begin(); it != end; ++it) { + typename Signal1_base::SlotType* slot = *it; + result = (*slot)(a1); + } + return result; + } + + template + R operator()(A1 a1, R default_result, const Merger& m) + { + R result(default_result); + Merger merger(m); + typename Signal1_base::SlotList::iterator end = Signal1_base::m_slots.end(); + for (typename Signal1_base::SlotList::iterator + it = Signal1_base::m_slots.begin(); it != end; ++it) { + typename Signal1_base::SlotType* slot = *it; + result = merger(result, (*slot)(a1)); + } + return result; + } + +}; + +// Signal1 +template +class Signal1 : public Signal1_base +{ +public: + Signal1() { } + + Signal1(const Signal1& s) + : Signal1_base(s) { } + + void operator()(A1 a1) + { + typename Signal1_base::SlotList::iterator end = Signal1_base::m_slots.end(); + for (typename Signal1_base::SlotList::iterator + it = Signal1_base::m_slots.begin(); it != end; ++it) { + typename Signal1_base::SlotType* slot = *it; + (*slot)(a1); + } + } + +}; + +// Signal2_base - Base class to delegate responsibility to +// functions of two arguments. +template +class Signal2_base +{ +public: + typedef R ReturnType; + typedef Slot2 SlotType; + typedef std::vector SlotList; + +protected: + SlotList m_slots; + +public: + Signal2_base() { } + Signal2_base(const Signal2_base& s) + { + copy(s); + } + ~Signal2_base() + { + disconnectAll(); + } + + SlotType* addSlot(SlotType* slot) + { + m_slots.push_back(slot); + return slot; + } + + template + SlotType* connect(const F& f) + { + return addSlot(new Slot2_fun(f)); + } + + template + SlotType* connect(R (T::*m)(A1, A2), T* t) + { + return addSlot(new Slot2_mem(m, t)); + } + + const SlotList& getSlots() const + { + return m_slots; + } + + void disconnect(SlotType* slot) + { + base::remove_from_container(m_slots, slot); + } + + void disconnectAll() + { + typename SlotList::iterator end = m_slots.end(); + for (typename SlotList::iterator + it = m_slots.begin(); it != end; ++it) + delete *it; + m_slots.clear(); + } + + bool empty() const + { + return m_slots.empty(); + } + + Signal2_base& operator=(const Signal2_base& s) { + copy(s); + return *this; + } + +private: + + void copy(const Signal2_base& s) + { + typename SlotList::const_iterator end = s.m_slots.end(); + for (typename SlotList::const_iterator + it = s.m_slots.begin(); it != end; ++it) { + m_slots.push_back((*it)->clone()); + } + } + +}; + +// Signal2 +template +class Signal2 : public Signal2_base +{ +public: + Signal2() { } + + Signal2(const Signal2& s) + : Signal2_base(s) { } + + R operator()(A1 a1, A2 a2, R default_result = R()) + { + R result(default_result); + typename Signal2_base::SlotList::iterator end = Signal2_base::m_slots.end(); + for (typename Signal2_base::SlotList::iterator + it = Signal2_base::m_slots.begin(); it != end; ++it) { + typename Signal2_base::SlotType* slot = *it; + result = (*slot)(a1, a2); + } + return result; + } + + template + R operator()(A1 a1, A2 a2, R default_result, const Merger& m) + { + R result(default_result); + Merger merger(m); + typename Signal2_base::SlotList::iterator end = Signal2_base::m_slots.end(); + for (typename Signal2_base::SlotList::iterator + it = Signal2_base::m_slots.begin(); it != end; ++it) { + typename Signal2_base::SlotType* slot = *it; + result = merger(result, (*slot)(a1, a2)); + } + return result; + } + +}; + +// Signal2 +template +class Signal2 : public Signal2_base +{ +public: + Signal2() { } + + Signal2(const Signal2& s) + : Signal2_base(s) { } + + void operator()(A1 a1, A2 a2) + { + typename Signal2_base::SlotList::iterator end = Signal2_base::m_slots.end(); + for (typename Signal2_base::SlotList::iterator + it = Signal2_base::m_slots.begin(); it != end; ++it) { + typename Signal2_base::SlotType* slot = *it; + (*slot)(a1, a2); + } + } + +}; + +#endif diff --git a/Runtime/Lua/LuaBind/signal/slot.h b/Runtime/Lua/LuaBind/signal/slot.h new file mode 100644 index 0000000..226d382 --- /dev/null +++ b/Runtime/Lua/LuaBind/signal/slot.h @@ -0,0 +1,203 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef BASE_SLOT_H_INCLUDED +#define BASE_SLOT_H_INCLUDED +#pragma once + +// Slot0 - Base class for delegates of zero arguments. +template +class Slot0 +{ +public: + Slot0() { } + Slot0(const Slot0& s) { (void)s; } + virtual ~Slot0() { } + virtual R operator()() = 0; + virtual Slot0* clone() const = 0; +}; + +// Slot0_fun - hold a F instance and use the function call operator +template +class Slot0_fun : public Slot0 +{ + F f; +public: + Slot0_fun(const F& f) : f(f) { } + Slot0_fun(const Slot0_fun& s) : Slot0(s), f(s.f) { } + ~Slot0_fun() { } + R operator()() { return f(); } + Slot0_fun* clone() const { return new Slot0_fun(*this); } +}; + +template +class Slot0_fun : public Slot0 +{ + F f; +public: + Slot0_fun(const F& f) : f(f) { } + Slot0_fun(const Slot0_fun& s) : Slot0(s), f(s.f) { } + ~Slot0_fun() { } + void operator()() { f(); } + Slot0_fun* clone() const { return new Slot0_fun(*this); } +}; + +// Slot0_mem - pointer to a member function of the T class +template +class Slot0_mem : public Slot0 +{ + R (T::*m)(); + T* t; +public: + Slot0_mem(R (T::*m)(), T* t) : m(m), t(t) { } + Slot0_mem(const Slot0_mem& s) : Slot0(s), m(s.m), t(s.t) { } + ~Slot0_mem() { } + R operator()() { return (t->*m)(); } + Slot0_mem* clone() const { return new Slot0_mem(*this); } +}; + +template +class Slot0_mem : public Slot0 +{ + void (T::*m)(); + T* t; +public: + Slot0_mem(void (T::*m)(), T* t) : m(m), t(t) { } + Slot0_mem(const Slot0_mem& s) : Slot0(s), m(s.m), t(s.t) { } + ~Slot0_mem() { } + void operator()() { (t->*m)(); } + Slot0_mem* clone() const { return new Slot0_mem(*this); } +}; + +// Slot1 - Base class for delegates of one argument. +template +class Slot1 +{ +public: + Slot1() { } + Slot1(const Slot1& s) { (void)s; } + virtual ~Slot1() { } + virtual R operator()(A1 a1) = 0; + virtual Slot1* clone() const = 0; +}; + +// Slot1_fun - hold a F instance and use the function call operator +template +class Slot1_fun : public Slot1 +{ + F f; +public: + Slot1_fun(const F& f) : f(f) { } + Slot1_fun(const Slot1_fun& s) : Slot1(s), f(s.f) { } + ~Slot1_fun() { } + R operator()(A1 a1) { return f(a1); } + Slot1_fun* clone() const { return new Slot1_fun(*this); } +}; + +template +class Slot1_fun : public Slot1 +{ + F f; +public: + Slot1_fun(const F& f) : f(f) { } + Slot1_fun(const Slot1_fun& s) : Slot1(s), f(s.f) { } + ~Slot1_fun() { } + void operator()(A1 a1) { f(a1); } + Slot1_fun* clone() const { return new Slot1_fun(*this); } +}; + +// Slot1_mem - pointer to a member function of the T class +template +class Slot1_mem : public Slot1 +{ + R (T::*m)(A1); + T* t; +public: + Slot1_mem(R (T::*m)(A1), T* t) : m(m), t(t) { } + Slot1_mem(const Slot1_mem& s) : Slot1(s), m(s.m), t(s.t) { } + ~Slot1_mem() { } + R operator()(A1 a1) { return (t->*m)(a1); } + Slot1_mem* clone() const { return new Slot1_mem(*this); } +}; + +template +class Slot1_mem : public Slot1 +{ + void (T::*m)(A1); + T* t; +public: + Slot1_mem(void (T::*m)(A1), T* t) : m(m), t(t) { } + Slot1_mem(const Slot1_mem& s) : Slot1(s), m(s.m), t(s.t) { } + ~Slot1_mem() { } + void operator()(A1 a1) { (t->*m)(a1); } + Slot1_mem* clone() const { return new Slot1_mem(*this); } +}; + +// Slot2 - Base class for delegates of two arguments. +template +class Slot2 +{ +public: + Slot2() { } + Slot2(const Slot2& s) { (void)s; } + virtual ~Slot2() { } + virtual R operator()(A1 a1, A2 a2) = 0; + virtual Slot2* clone() const = 0; +}; + +// Slot2_fun - hold a F instance and use the function call operator +template +class Slot2_fun : public Slot2 +{ + F f; +public: + Slot2_fun(const F& f) : f(f) { } + Slot2_fun(const Slot2_fun& s) : Slot2(s), f(s.f) { } + ~Slot2_fun() { } + R operator()(A1 a1, A2 a2) { return f(a1, a2); } + Slot2_fun* clone() const { return new Slot2_fun(*this); } +}; + +template +class Slot2_fun : public Slot2 +{ + F f; +public: + Slot2_fun(const F& f) : f(f) { } + Slot2_fun(const Slot2_fun& s) : Slot2(s), f(s.f) { } + ~Slot2_fun() { } + void operator()(A1 a1, A2 a2) { f(a1, a2); } + Slot2_fun* clone() const { return new Slot2_fun(*this); } +}; + +// Slot2_mem - pointer to a member function of the T class +template +class Slot2_mem : public Slot2 +{ + R (T::*m)(A1, A2); + T* t; +public: + Slot2_mem(R (T::*m)(A1, A2), T* t) : m(m), t(t) { } + Slot2_mem(const Slot2_mem& s) : Slot2(s), m(s.m), t(s.t) { } + ~Slot2_mem() { } + R operator()(A1 a1, A2 a2) { return (t->*m)(a1, a2); } + Slot2_mem* clone() const { return new Slot2_mem(*this); } +}; + +template +class Slot2_mem : public Slot2 +{ + void (T::*m)(A1, A2); + T* t; +public: + Slot2_mem(void (T::*m)(A1, A2), T* t) : m(m), t(t) { } + Slot2_mem(const Slot2_mem& s) : Slot2(s), m(s.m), t(s.t) { } + ~Slot2_mem() { } + void operator()(A1 a1, A2 a2) { return (t->*m)(a1, a2); } + Slot2_mem* clone() const { return new Slot2_mem(*this); } +}; + +#endif -- cgit v1.1-26-g67d0