summaryrefslogtreecommitdiff
path: root/Runtime/Lua/LuaBind
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-22 23:59:54 +0800
committerchai <chaifix@163.com>2021-10-22 23:59:54 +0800
commit4dafefe46a72ba47468b13d011f8299055081b0f (patch)
tree2a85835ec4d74fecf3815397b384cefe39d31f56 /Runtime/Lua/LuaBind
parent1f18d2afec632aa9361079ca3bcb5a7f2d73db3a (diff)
*LuaBind
Diffstat (limited to 'Runtime/Lua/LuaBind')
-rw-r--r--Runtime/Lua/LuaBind/LuaBindClass.cpp2
-rw-r--r--Runtime/Lua/LuaBind/LuaBindClass.hpp150
-rw-r--r--Runtime/Lua/LuaBind/LuaBindHelper.cpp0
-rw-r--r--Runtime/Lua/LuaBind/LuaBindHelper.h16
-rw-r--r--Runtime/Lua/LuaBind/LuaBindMemberRef.h2
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRef.cpp72
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRef.h21
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRefTable.cpp34
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRefTable.h15
-rw-r--r--Runtime/Lua/LuaBind/LuaBindState.h43
-rw-r--r--Runtime/Lua/LuaBind/LuaBindUtility.h14
-rw-r--r--Runtime/Lua/LuaBind/LuaBindVM.cpp40
-rw-r--r--Runtime/Lua/LuaBind/LuaBindVM.h19
-rw-r--r--Runtime/Lua/LuaBind/signal/bind.h510
-rw-r--r--Runtime/Lua/LuaBind/signal/remove_from_container.h32
-rw-r--r--Runtime/Lua/LuaBind/signal/signal.h451
-rw-r--r--Runtime/Lua/LuaBind/signal/slot.h203
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