diff options
author | chai <chaifix@163.com> | 2021-10-22 23:59:54 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-10-22 23:59:54 +0800 |
commit | 4dafefe46a72ba47468b13d011f8299055081b0f (patch) | |
tree | 2a85835ec4d74fecf3815397b384cefe39d31f56 /Runtime/Lua/LuaBind | |
parent | 1f18d2afec632aa9361079ca3bcb5a7f2d73db3a (diff) |
*LuaBind
Diffstat (limited to 'Runtime/Lua/LuaBind')
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindClass.cpp | 2 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindClass.hpp | 150 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindHelper.cpp | 0 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindHelper.h | 16 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindMemberRef.h | 2 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindRef.cpp | 72 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindRef.h | 21 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindRefTable.cpp | 34 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindRefTable.h | 15 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindState.h | 43 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindUtility.h | 14 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindVM.cpp | 40 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindVM.h | 19 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/signal/bind.h | 510 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/signal/remove_from_container.h | 32 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/signal/signal.h | 451 | ||||
-rw-r--r-- | Runtime/Lua/LuaBind/signal/slot.h | 203 |
17 files changed, 1388 insertions, 236 deletions
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 <unordered_set> -#endif - +#include <unordered_map> #include <vector> - #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 TYPE, class BASE = Object> class NativeClass : public BASE { public: + enum NativeClassTableIndex { kRefTable = 1, kMemberTable = 2, kClassTable = 3 }; - // // 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。 // 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体, // 避免lua频繁的调用gc检测。 - // template<class DATATYPE> void Retain(State& state, DATATYPE* userdata); - // // 对userdata减少一个引用在ref table里,以尝试回收userdata。 - // template<class DATATYPE> 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<class TYPE, class BASE> + int NativeClass<TYPE, BASE>::sClassID = CLASS_NONE_ID; - // // 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 - // template<class TYPE, class BASE> int NativeClass<TYPE, BASE>::_GetClassName(lua_State* L) { @@ -220,9 +192,7 @@ namespace LuaBind //--------------------------------------------------------------------------------// - // // 注册工厂和单例共有的类成员 - // template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::RegisterClassShared(State& state) { @@ -235,9 +205,7 @@ namespace LuaBind state.RegisterMethods(regTable); } - // // 工厂类的成员,注册在class table - // template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::RegisterFactoryClass(State& state) { @@ -249,36 +217,27 @@ namespace LuaBind state.RegisterMethods(regTable); } - // - // 单例类的成员,注册在class table - // template<class TYPE, class BASE> - void NativeClass<TYPE, BASE>::RegisterSingletonClass(State& state) + void NativeClass<TYPE, BASE>::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<class TYPE, class BASE> void NativeClass<TYPE, BASE>::PushClassTable(State& state) { - assert(mClassTable); - - mClassTable.PushRef(state); + LuaBind::VM* vm = state.GetVM(); + vm->PushClassTable(state, sClassID); } template<class TYPE, class BASE> - void NativeClass<TYPE, BASE>::SetClassTableRef(State& state, int idx) - { - mClassTable.SetRef(state, idx); - } - - template<class TYPE, class BASE> - NativeClass<TYPE, BASE>::NativeClass() + NativeClass<TYPE, BASE>::NativeClass(LuaBind::VM* vm) : mWatchDog() + , mUserdata(vm) + , mOwner(vm) #if LUA_BIND_PROFILER , mSafer(false) #endif @@ -380,8 +339,7 @@ namespace LuaBind template<class TYPE, class BASE> bool NativeClass<TYPE, BASE>::PushUserdata(State& state) { - assert(!TYPE::IsClassSingleton()); - if (!mUserdata) + if (!mUserdata) // 第一次创建 { BindToLua(state); return true; @@ -413,28 +371,12 @@ namespace LuaBind template<class TYPE, class BASE> bool NativeClass<TYPE, BASE>::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<class TYPE, class BASE> void NativeClass<TYPE, BASE>::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<class TYPE, class BASE> void NativeClass<TYPE, BASE>::SetMemberRef(State& state, MemberRef& memRef, int idx) { @@ -810,10 +748,7 @@ namespace LuaBind int NativeClass<TYPE, BASE>::_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<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mClassTable; // class table - template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::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 --- /dev/null +++ b/Runtime/Lua/LuaBind/LuaBindHelper.cpp 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<class TYPE> void RegisterFactory(); - // 注册单例,没有New方法 - template<class TYPE> 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<typename TYPE> - 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<type,##__VA_ARGS__>; \ - 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<param>() -#define LUA_BIND_REGISTER_SINGLETON(state, param) state.RegisterSingleton<param>() #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<global_State*, VM*> 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<global_State*, VM*>(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<int, StrongRef>(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 <map> #include <unordered_set> +#include <unordered_map> #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<global_State*, VM*> VMap; + private: + static std::map<global_State*, VM*> 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<int/*ClassID*/, StrongRef> 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<typename R, typename F> +class BindAdapter0_fun +{ + F f; +public: + BindAdapter0_fun(const F& f) : f(f) { } + + R operator()() { return f(); } + + template<typename A1> + R operator()(const A1& a1) { return f(); } + + template<typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return f(); } + + template<typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(); } + + template<typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(); } +}; + +template<typename F> +class BindAdapter0_fun<void, F> +{ + F f; +public: + BindAdapter0_fun(const F& f) : f(f) { } + + void operator()() { f(); } + + template<typename A1> + void operator()(const A1& a1) { f(); } + + template<typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { f(); } + + template<typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(); } + + template<typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(); } +}; + +template<typename R, typename F> +BindAdapter0_fun<R, F> +Bind(const F& f) +{ + return BindAdapter0_fun<R, F>(f); +} + +// BindAdapter0_mem +template<typename R, typename T> +class BindAdapter0_mem +{ + R (T::*m)(); + T* t; +public: + template<typename T2> + BindAdapter0_mem(R (T::*m)(), T2* t) : m(m), t(t) { } + + R operator()() { return (t->*m)(); } + + template <typename A1> + R operator()(const A1& a1) { return (t->*m)(); } + + template <typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return (t->*m)(); } + + template <typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(); } + + template <typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(); } +}; + +template<typename T> +class BindAdapter0_mem<void, T> +{ + void (T::*m)(); + T* t; +public: + template<typename T2> + BindAdapter0_mem(void (T::*m)(), T2* t) : m(m), t(t) { } + + void operator()() { (t->*m)(); } + + template <typename A1> + void operator()(const A1& a1) { (t->*m)(); } + + template <typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { (t->*m)(); } + + template <typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(); } + + template <typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(); } +}; + +template<typename R, typename T, typename T2> +BindAdapter0_mem<R, T> +Bind(R (T::*m)(), T2* t) +{ + return BindAdapter0_mem<R, T>(m, t); +} + +// BindAdapter1_fun +template<typename R, typename F, + typename X1> +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<typename A1> + R operator()(const A1& a1) { return f(x1); } + + template<typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return f(x1); } + + template<typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1); } + + template<typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1); } +}; + +template<typename F, + typename X1> +class BindAdapter1_fun<void, F, X1> +{ + F f; + X1 x1; +public: + BindAdapter1_fun(const F& f, X1 x1) : f(f), x1(x1) { } + + void operator()() { f(x1); } + + template<typename A1> + void operator()(const A1& a1) { f(x1); } + + template<typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { f(x1); } + + template<typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1); } + + template<typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1); } +}; + +template<typename R, typename F, + typename X1> +BindAdapter1_fun<R, F, X1> +Bind(const F& f, X1 x1) +{ + return BindAdapter1_fun<R, F, X1>(f, x1); +} + +// BindAdapter1_mem +template<typename R, typename T, + typename B1, + typename X1> +class BindAdapter1_mem +{ + R (T::*m)(B1); + T* t; + X1 x1; +public: + template<typename T2> + BindAdapter1_mem(R (T::*m)(B1), T2* t, X1 x1) : m(m), t(t), x1(x1) { } + + R operator()() { return (t->*m)(x1); } + + template <typename A1> + R operator()(const A1& a1) { return (t->*m)(x1); } + + template <typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1); } + + template <typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1); } + + template <typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1); } +}; + +template<typename T, + typename B1, + typename X1> +class BindAdapter1_mem<void, T, B1, X1> +{ + void (T::*m)(B1); + T* t; + X1 x1; +public: + template<typename T2> + BindAdapter1_mem(void (T::*m)(B1), T2* t, X1 x1) : m(m), t(t), x1(x1) { } + + void operator()() { (t->*m)(x1); } + + template <typename A1> + void operator()(const A1& a1) { (t->*m)(x1); } + + template <typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { (t->*m)(x1); } + + template <typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1); } + + template <typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1); } +}; + +template<typename R, typename T, typename T2, + typename B1, typename X1> +BindAdapter1_mem<R, T, B1, X1> +Bind(R (T::*m)(B1), T2* t, X1 x1) +{ + return BindAdapter1_mem<R, T, B1, X1>(m, t, x1); +} + +// BindAdapter2_fun +template<typename R, typename F, + typename X1, typename X2> +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<typename A1> + R operator()(const A1& a1) { return f(x1, x2); } + + template<typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return f(x1, x2); } + + template<typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2); } + + template<typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2); } +}; + +template<typename F, + typename X1, typename X2> +class BindAdapter2_fun<void, F, X1, X2> +{ + 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<typename A1> + void operator()(const A1& a1) { f(x1, x2); } + + template<typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { f(x1, x2); } + + template<typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2); } + + template<typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2); } +}; + +template<typename R, typename F, + typename X1, typename X2> +BindAdapter2_fun<R, F, X1, X2> +Bind(const F& f, X1 x1, X2 x2) +{ + return BindAdapter2_fun<R, F, X1, X2>(f, x1, x2); +} + +// BindAdapter2_mem +template<typename R, typename T, + typename B1, typename B2, + typename X1, typename X2> +class BindAdapter2_mem +{ + R (T::*m)(B1, B2); + T* t; + X1 x1; + X2 x2; +public: + template<typename T2> + 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<typename A1> + R operator()(const A1& a1) { return (t->*m)(x1, x2); } + + template<typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2); } + + template<typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2); } + + template<typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2); } +}; + +template<typename T, + typename B1, typename B2, + typename X1, typename X2> +class BindAdapter2_mem<void, T, B1, B2, X1, X2> +{ + void (T::*m)(B1, B2); + T* t; + X1 x1; + X2 x2; +public: + template<typename T2> + 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<typename A1> + void operator()(const A1& a1) { (t->*m)(x1, x2); } + + template<typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2); } + + template<typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2); } + + template<typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2); } +}; + +template<typename R, typename T, typename T2, typename B1, typename B2, typename X1, typename X2> +BindAdapter2_mem<R, T, B1, B2, X1, X2> +Bind(R (T::*m)(B1, B2), T2* t, X1 x1, X2 x2) +{ + return BindAdapter2_mem<R, T, B1, B2, X1, X2>(m, t, x1, x2); +} + +// BindAdapter3_fun +template<typename R, typename F, + typename X1, typename X2, typename X3> +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<typename A1> + R operator()(const A1& a1) { return f(x1, x2, x3); } + + template<typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return f(x1, x2, x3); } + + template<typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2, x3); } + + template<typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2, x3); } +}; + +template<typename F, + typename X1, typename X2, typename X3> +class BindAdapter3_fun<void, F, X1, X2, X3> +{ + 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<typename A1> + void operator()(const A1& a1) { f(x1, x2, x3); } + + template<typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { f(x1, x2, x3); } + + template<typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2, x3); } + + template<typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2, x3); } +}; + +template<typename R, typename F, + typename X1, typename X2, typename X3> +BindAdapter3_fun<R, F, X1, X2, X3> +Bind(const F& f, X1 x1, X2 x2, X3 x3) +{ + return BindAdapter3_fun<R, F, X1, X2, X3>(f, x1, x2, x3); +} + +// BindAdapter3_mem +template<typename R, typename T, + typename B1, typename B2, typename B3, + typename X1, typename X2, typename X3> +class BindAdapter3_mem +{ + R (T::*m)(B1, B2, B3); + T* t; + X1 x1; + X2 x2; + X3 x3; +public: + template<typename T2> + 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<typename A1> + R operator()(const A1& a1) { return (t->*m)(x1, x2, x3); } + + template<typename A1, typename A2> + R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2, x3); } + + template<typename A1, typename A2, typename A3> + R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2, x3); } + + template<typename A1, typename A2, typename A3, typename A4> + R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2, x3); } +}; + +template<typename T, + typename B1, typename B2, typename B3, + typename X1, typename X2, typename X3> +class BindAdapter3_mem<void, T, B1, B2, B3, X1, X2, X3> +{ + void (T::*m)(B1, B2, B3); + T* t; + X1 x1; + X2 x2; + X3 x3; +public: + template<typename T2> + 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<typename A1> + void operator()(const A1& a1) { (t->*m)(x1, x2, x3); } + + template<typename A1, typename A2> + void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2, x3); } + + template<typename A1, typename A2, typename A3> + void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2, x3); } + + template<typename A1, typename A2, typename A3, typename A4> + void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2, x3); } +}; + +template<typename R, typename T, typename T2, + typename B1, typename B2, typename B3, + typename X1, typename X2, typename X3> +BindAdapter3_mem<R, T, B1, B2, B3, X1, X2, X3> +Bind(R (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2) +{ + return BindAdapter3_mem<R, T, B1, B2, B3, X1, X2, X3>(m, t, x1, x2); +} + +// Helper class to holds references as pointers (to avoid copying the +// original object). +template<class T> +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<class T> +RefWrapper<T> Ref(T& ref) +{ + return RefWrapper<T>(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<typename ContainerType>
+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 <vector>
+
+// Signal0_base<R> - Base class to delegate responsibility to
+// functions of zero arguments.
+template<typename R>
+class Signal0_base
+{
+public:
+ typedef R ReturnType;
+ typedef Slot0<R> SlotType;
+ typedef std::vector<SlotType*> SlotList;
+
+protected:
+ SlotList m_slots;
+
+public:
+ Signal0_base() { }
+ Signal0_base(const Signal0_base<R>& s)
+ {
+ copy(s);
+ }
+ ~Signal0_base()
+ {
+ disconnectAll();
+ }
+
+ SlotType* addSlot(SlotType* slot)
+ {
+ m_slots.push_back(slot);
+ return slot;
+ }
+
+ template<typename F>
+ SlotType* connect(const F& f)
+ {
+ return addSlot(new Slot0_fun<R, F>(f));
+ }
+
+ template<class T>
+ SlotType* connect(R (T::*m)(), T* t)
+ {
+ return addSlot(new Slot0_mem<R, T>(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<R>& s) {
+ copy(s);
+ return *this;
+ }
+
+private:
+
+ void copy(const Signal0_base<R>& 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<R>
+template<typename R>
+class Signal0 : public Signal0_base<R>
+{
+public:
+ Signal0() { }
+
+ Signal0(const Signal0<R>& s)
+ : Signal0_base<R>(s) { }
+
+ R operator()(R default_result = R())
+ {
+ R result(default_result);
+ typename Signal0_base<R>::SlotList::iterator end = Signal0_base<R>::m_slots.end();
+ for (typename Signal0_base<R>::SlotList::iterator
+ it = Signal0_base<R>::m_slots.begin(); it != end; ++it) {
+ typename Signal0_base<R>::SlotType* slot = *it;
+ result = (*slot)();
+ }
+ return result;
+ }
+
+ template<typename Merger>
+ R operator()(R default_result, const Merger& m)
+ {
+ R result(default_result);
+ Merger merger(m);
+ typename Signal0_base<R>::SlotList::iterator end = Signal0_base<R>::m_slots.end();
+ for (typename Signal0_base<R>::SlotList::iterator
+ it = Signal0_base<R>::m_slots.begin(); it != end; ++it) {
+ typename Signal0_base<R>::SlotType* slot = *it;
+ result = merger(result, (*slot)());
+ }
+ return result;
+ }
+
+};
+
+// Signal0<void>
+template<>
+class Signal0<void> : public Signal0_base<void>
+{
+public:
+ Signal0() { }
+
+ Signal0(const Signal0<void>& s)
+ : Signal0_base<void>(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<R, A1> - Base class to delegate responsibility to
+// functions of one argument.
+template<typename R, typename A1>
+class Signal1_base
+{
+public:
+ typedef R ReturnType;
+ typedef Slot1<R, A1> SlotType;
+ typedef std::vector<SlotType*> SlotList;
+
+protected:
+ SlotList m_slots;
+
+public:
+ Signal1_base() { }
+ Signal1_base(const Signal1_base<R, A1>& s)
+ {
+ copy(s);
+ }
+ ~Signal1_base()
+ {
+ disconnectAll();
+ }
+
+ SlotType* addSlot(SlotType* slot)
+ {
+ m_slots.push_back(slot);
+ return slot;
+ }
+
+ template<typename F>
+ SlotType* connect(const F& f)
+ {
+ return addSlot(new Slot1_fun<R, F, A1>(f));
+ }
+
+ template<class T>
+ SlotType* connect(R (T::*m)(A1), T* t)
+ {
+ return addSlot(new Slot1_mem<R, T, A1>(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<R, A1>& s) {
+ copy(s);
+ return *this;
+ }
+
+private:
+
+ void copy(const Signal1_base<R, A1>& 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<R, A1>
+template<typename R, typename A1>
+class Signal1 : public Signal1_base<R, A1>
+{
+public:
+ Signal1() { }
+
+ Signal1(const Signal1<R, A1>& s)
+ : Signal1_base<R, A1>(s) { }
+
+ R operator()(A1 a1, R default_result = R())
+ {
+ R result(default_result);
+ typename Signal1_base<R, A1>::SlotList::iterator end = Signal1_base<R, A1>::m_slots.end();
+ for (typename Signal1_base<R, A1>::SlotList::iterator
+ it = Signal1_base<R, A1>::m_slots.begin(); it != end; ++it) {
+ typename Signal1_base<R, A1>::SlotType* slot = *it;
+ result = (*slot)(a1);
+ }
+ return result;
+ }
+
+ template<typename Merger>
+ R operator()(A1 a1, R default_result, const Merger& m)
+ {
+ R result(default_result);
+ Merger merger(m);
+ typename Signal1_base<R, A1>::SlotList::iterator end = Signal1_base<R, A1>::m_slots.end();
+ for (typename Signal1_base<R, A1>::SlotList::iterator
+ it = Signal1_base<R, A1>::m_slots.begin(); it != end; ++it) {
+ typename Signal1_base<R, A1>::SlotType* slot = *it;
+ result = merger(result, (*slot)(a1));
+ }
+ return result;
+ }
+
+};
+
+// Signal1<void, A1>
+template<typename A1>
+class Signal1<void, A1> : public Signal1_base<void, A1>
+{
+public:
+ Signal1() { }
+
+ Signal1(const Signal1<void, A1>& s)
+ : Signal1_base<void, A1>(s) { }
+
+ void operator()(A1 a1)
+ {
+ typename Signal1_base<void, A1>::SlotList::iterator end = Signal1_base<void, A1>::m_slots.end();
+ for (typename Signal1_base<void, A1>::SlotList::iterator
+ it = Signal1_base<void, A1>::m_slots.begin(); it != end; ++it) {
+ typename Signal1_base<void, A1>::SlotType* slot = *it;
+ (*slot)(a1);
+ }
+ }
+
+};
+
+// Signal2_base<R, A1, A2> - Base class to delegate responsibility to
+// functions of two arguments.
+template<typename R, typename A1, typename A2>
+class Signal2_base
+{
+public:
+ typedef R ReturnType;
+ typedef Slot2<R, A1, A2> SlotType;
+ typedef std::vector<SlotType*> SlotList;
+
+protected:
+ SlotList m_slots;
+
+public:
+ Signal2_base() { }
+ Signal2_base(const Signal2_base<R, A1, A2>& s)
+ {
+ copy(s);
+ }
+ ~Signal2_base()
+ {
+ disconnectAll();
+ }
+
+ SlotType* addSlot(SlotType* slot)
+ {
+ m_slots.push_back(slot);
+ return slot;
+ }
+
+ template<typename F>
+ SlotType* connect(const F& f)
+ {
+ return addSlot(new Slot2_fun<R, F, A1, A2>(f));
+ }
+
+ template<class T>
+ SlotType* connect(R (T::*m)(A1, A2), T* t)
+ {
+ return addSlot(new Slot2_mem<R, T, A1, A2>(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<R, A1, A2>& s) {
+ copy(s);
+ return *this;
+ }
+
+private:
+
+ void copy(const Signal2_base<R, A1, A2>& 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<R, A1>
+template<typename R, typename A1, typename A2>
+class Signal2 : public Signal2_base<R, A1, A2>
+{
+public:
+ Signal2() { }
+
+ Signal2(const Signal2<R, A1, A2>& s)
+ : Signal2_base<R, A1, A2>(s) { }
+
+ R operator()(A1 a1, A2 a2, R default_result = R())
+ {
+ R result(default_result);
+ typename Signal2_base<R, A1, A2>::SlotList::iterator end = Signal2_base<R, A1, A2>::m_slots.end();
+ for (typename Signal2_base<R, A1, A2>::SlotList::iterator
+ it = Signal2_base<R, A1, A2>::m_slots.begin(); it != end; ++it) {
+ typename Signal2_base<R, A1, A2>::SlotType* slot = *it;
+ result = (*slot)(a1, a2);
+ }
+ return result;
+ }
+
+ template<typename Merger>
+ R operator()(A1 a1, A2 a2, R default_result, const Merger& m)
+ {
+ R result(default_result);
+ Merger merger(m);
+ typename Signal2_base<R, A1, A2>::SlotList::iterator end = Signal2_base<R, A1, A2>::m_slots.end();
+ for (typename Signal2_base<R, A1, A2>::SlotList::iterator
+ it = Signal2_base<R, A1, A2>::m_slots.begin(); it != end; ++it) {
+ typename Signal2_base<R, A1, A2>::SlotType* slot = *it;
+ result = merger(result, (*slot)(a1, a2));
+ }
+ return result;
+ }
+
+};
+
+// Signal2<void, A1>
+template<typename A1, typename A2>
+class Signal2<void, A1, A2> : public Signal2_base<void, A1, A2>
+{
+public:
+ Signal2() { }
+
+ Signal2(const Signal2<void, A1, A2>& s)
+ : Signal2_base<void, A1, A2>(s) { }
+
+ void operator()(A1 a1, A2 a2)
+ {
+ typename Signal2_base<void, A1, A2>::SlotList::iterator end = Signal2_base<void, A1, A2>::m_slots.end();
+ for (typename Signal2_base<void, A1, A2>::SlotList::iterator
+ it = Signal2_base<void, A1, A2>::m_slots.begin(); it != end; ++it) {
+ typename Signal2_base<void, A1, A2>::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<typename R>
+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<typename R, typename F>
+class Slot0_fun : public Slot0<R>
+{
+ F f;
+public:
+ Slot0_fun(const F& f) : f(f) { }
+ Slot0_fun(const Slot0_fun& s) : Slot0<R>(s), f(s.f) { }
+ ~Slot0_fun() { }
+ R operator()() { return f(); }
+ Slot0_fun* clone() const { return new Slot0_fun(*this); }
+};
+
+template<typename F>
+class Slot0_fun<void, F> : public Slot0<void>
+{
+ F f;
+public:
+ Slot0_fun(const F& f) : f(f) { }
+ Slot0_fun(const Slot0_fun& s) : Slot0<void>(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<typename R, class T>
+class Slot0_mem : public Slot0<R>
+{
+ R (T::*m)();
+ T* t;
+public:
+ Slot0_mem(R (T::*m)(), T* t) : m(m), t(t) { }
+ Slot0_mem(const Slot0_mem& s) : Slot0<R>(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 T>
+class Slot0_mem<void, T> : public Slot0<void>
+{
+ void (T::*m)();
+ T* t;
+public:
+ Slot0_mem(void (T::*m)(), T* t) : m(m), t(t) { }
+ Slot0_mem(const Slot0_mem& s) : Slot0<void>(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<typename R, typename A1>
+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<typename R, typename F, typename A1>
+class Slot1_fun : public Slot1<R, A1>
+{
+ F f;
+public:
+ Slot1_fun(const F& f) : f(f) { }
+ Slot1_fun(const Slot1_fun& s) : Slot1<R, A1>(s), f(s.f) { }
+ ~Slot1_fun() { }
+ R operator()(A1 a1) { return f(a1); }
+ Slot1_fun* clone() const { return new Slot1_fun(*this); }
+};
+
+template<typename F, typename A1>
+class Slot1_fun<void, F, A1> : public Slot1<void, A1>
+{
+ F f;
+public:
+ Slot1_fun(const F& f) : f(f) { }
+ Slot1_fun(const Slot1_fun& s) : Slot1<void, A1>(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<typename R, class T, typename A1>
+class Slot1_mem : public Slot1<R, A1>
+{
+ 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<R, A1>(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 T, typename A1>
+class Slot1_mem<void, T, A1> : public Slot1<void, A1>
+{
+ 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<void, A1>(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<typename R, typename A1, typename A2>
+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<typename R, typename F, typename A1, typename A2>
+class Slot2_fun : public Slot2<R, A1, A2>
+{
+ F f;
+public:
+ Slot2_fun(const F& f) : f(f) { }
+ Slot2_fun(const Slot2_fun& s) : Slot2<R, A1, A2>(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<typename F, typename A1, typename A2>
+class Slot2_fun<void, F, A1, A2> : public Slot2<void, A1, A2>
+{
+ F f;
+public:
+ Slot2_fun(const F& f) : f(f) { }
+ Slot2_fun(const Slot2_fun& s) : Slot2<void, A1, A2>(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<typename R, class T, typename A1, typename A2>
+class Slot2_mem : public Slot2<R, A1, A2>
+{
+ 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<R, A1, A2>(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 T, typename A1, typename A2>
+class Slot2_mem<void, T, A1, A2> : public Slot2<void, A1, A2>
+{
+ 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<void, A1, A2>(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
|