在C++中实现delegate
delegate.h
#ifndef WAN_DELEGATE_H
#define WAN_DELEGATE_H
/**
* @author Kevin Wan <wanjunfeng@gmail.com>
* @date 06/30/2005
* Copyright (C) Kevin Wan
*/
#include "threadingmodel.h"
namespace wan
{
namespace local
{
template <typename> class ICallback;
template <typename> class NativeCallback;
template <typename, typename> class MemberCallback;
} // namespace local
#ifndef WAN_DELEGATE_H
#define WAN_DELEGATE_H
/**
* @author Kevin Wan <wanjunfeng@gmail.com>
* @date 06/30/2005
* Copyright (C) Kevin Wan
*/
#include "threadingmodel.h"
namespace wan
{
namespace local
{
template <typename> class ICallback;
template <typename> class NativeCallback;
template <typename, typename> class MemberCallback;
} // namespace local
template <typename, typename LockType = void> class delegate;
#define DELEGATE_GENERATOR(TEMPLATE_LIST, TYPE_LIST, TYPE_PARAM_LIST,
PARAM_LIST) \
namespace local \
{ \
template <typename ReturnType TEMPLATE_LIST> \
class ICallback<ReturnType(TYPE_LIST)> \
{ \
typedef ICallback<ReturnType(TYPE_LIST)> SelfType; \
\
public: \
virtual ~ICallback() {} \
\
virtual ReturnType invoke(TYPE_LIST) const = 0; \
virtual bool equals(const SelfType* pDelegate) const = 0; \
virtual SelfType* clone() const = 0; \
}; \
\
template <typename ReturnType TEMPLATE_LIST> \
class NativeCallback<ReturnType(TYPE_LIST)> \
: public ICallback<ReturnType(TYPE_LIST)> \
{ \
typedef ICallback<ReturnType(TYPE_LIST)> SuperType; \
typedef NativeCallback<ReturnType(TYPE_LIST)> SelfType; \
typedef ReturnType (*FunctionPtr)(TYPE_LIST); \
\
public: \
explicit NativeCallback(FunctionPtr ptr) \
: m_handler(ptr) \
{ \
} \
\
NativeCallback(const SelfType& rhs) \
: ICallback<ReturnType(TYPE_LIST)>(rhs) \
, m_handler(rhs.m_handler) \
{ \
} \
\
ReturnType invoke(TYPE_PARAM_LIST) const \
{ \
return (*m_handler)(PARAM_LIST); \
} \
\
bool equals(const SuperType* pDelegate) const \
{ \
const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
if (pRhs == 0) return false; \
if (m_handler == pRhs->m_handler) return true; \
return false; \
} \
\
SelfType* clone() const \
{ \
return new SelfType(*this); \
} \
\
private: \
FunctionPtr m_handler; \
}; \
\
template <typename ObjectType, typename ReturnType TEMPLATE_LIST> \
class MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
: public ICallback<ReturnType(TYPE_LIST)> \
{ \
typedef ICallback<ReturnType(TYPE_LIST)> SuperType; \
typedef MemberCallback<ObjectType, ReturnType(TYPE_LIST)> SelfType; \
typedef ReturnType (ObjectType::*FunctionPtr)(TYPE_LIST); \
typedef ReturnType (ObjectType::*ConstFunctionPtr)(TYPE_LIST) const; \
\
enum { CONST_POINTER, NEED_DELETE, DONT_DELETE }; \
struct ObjectManager \
{ \
bool equals(const ObjectManager& rhs) \
{ \
return object.pObject == rhs.object.pObject; \
} \
\
union { ObjectType* pObject; const ObjectType* pConstObject; } object; \
int property; \
int refCount; \
}; \
\
public: \
MemberCallback(ObjectType* t, FunctionPtr ptr, bool needDelete = false) \
: m_isConstMemFunc(false) \
{ \
m_pObjectManager = new ObjectManager(); \
m_pObjectManager->object.pObject = t; \
m_pObjectManager->property = needDelete ? NEED_DELETE : DONT_DELETE; \
m_pObjectManager->refCount = 0; \
m_handler.ptr = ptr; \
incrementRefCount(); \
} \
\
MemberCallback(ObjectType* t, ConstFunctionPtr ptr, bool needDelete = false) \
: m_isConstMemFunc(true) \
{ \
m_pObjectManager = new ObjectManager(); \
m_pObjectManager->object.pObject = t; \
m_pObjectManager->property = needDelete ? NEED_DELETE : DONT_DELETE; \
m_pObjectManager->refCount = 0; \
m_handler.constPtr = ptr; \
incrementRefCount(); \
} \
\
MemberCallback(const ObjectType* t, ConstFunctionPtr ptr) \
: m_isConstMemFunc(true) \
{ \
m_pObjectManager = new ObjectManager(); \
m_pObjectManager->object.pConstObject = t; \
m_pObjectManager->property = CONST_POINTER; \
m_pObjectManager->refCount = 0; \
m_handler.constPtr = ptr; \
incrementRefCount(); \
} \
\
MemberCallback(const SelfType& rhs) \
: ICallback<ReturnType(TYPE_LIST)>(rhs) \
, m_pObjectManager(rhs.m_pObjectManager) \
, m_handler(rhs.m_handler) \
, m_isConstMemFunc(rhs.m_isConstMemFunc) \
{ \
incrementRefCount(); \
} \
\
virtual ~MemberCallback() \
{ \
decrementRefCount(); \
} \
\
MemberCallback& operator=(const SelfType& rhs) \
{ \
if (this == &rhs) \
return *this; \
decrementRefCount(); \
m_pObjectManager = rhs.m_pObjectManager; \
m_handler = rhs.m_handler; \
m_isConstMemFunc = rhs.m_isConstMemFunc; \
incrementRefCount(); \
return *this; \
} \
\
ReturnType invoke(TYPE_PARAM_LIST) const \
{ \
if (m_isConstMemFunc) \
{ \
if (m_pObjectManager->property == CONST_POINTER) \
return (m_pObjectManager->object.pConstObject->*(m_handler.constPtr))(PARAM_LIST); \
return (m_pObjectManager->object.pObject->*(m_handler.constPtr))(PARAM_LIST); \
} \
return (m_pObjectManager->object.pObject->*(m_handler.ptr))(PARAM_LIST); \
} \
\
bool equals(const SuperType* pDelegate) const \
{ \
const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
if (pRhs == 0) return false; \
if (m_pObjectManager->equals(*pRhs->m_pObjectManager) \
&& m_isConstMemFunc == pRhs->m_isConstMemFunc \
&& m_handler.ptr == pRhs->m_handler.ptr) \
return true; \
return false; \
} \
\
SelfType* clone() const \
{ \
return new SelfType(*this); \
} \
\
private: \
void incrementRefCount() \
{ \
++m_pObjectManager->refCount; \
} \
\
void decrementRefCount() \
{ \
if (--m_pObjectManager->refCount == 0) \
{ \
if (m_pObjectManager->property == NEED_DELETE) \
delete m_pObjectManager->object.pObject; \
\
delete m_pObjectManager; \
} \
} \
\
private: \
ObjectManager* m_pObjectManager; \
union { FunctionPtr ptr; ConstFunctionPtr constPtr; } m_handler; \
bool m_isConstMemFunc; \
}; \
} /* namespace local */ \
\
template <typename ReturnType TEMPLATE_LIST, typename LockType> \
class delegate<ReturnType(TYPE_LIST), LockType> \
: public local::ICallback<ReturnType(TYPE_LIST)> \
, public ThreadingModel<LockType> \
{ \
typedef local::ICallback<ReturnType(TYPE_LIST)> SuperType; \
typedef delegate<ReturnType(TYPE_LIST), LockType> SelfType; \
typedef ThreadingModel<LockType> ThreadingModelType; \
struct CallbackHolder \
{ \
SuperType* instance; \
CallbackHolder* prev; \
ReturnType call(TYPE_PARAM_LIST) \
{ \
if (prev != 0) prev->call(PARAM_LIST); \
return instance->invoke(PARAM_LIST); \
} \
}; \
\
public: \
delegate() : m_pHolder(0) {} \
\
explicit delegate(ReturnType (*ptr)(TYPE_LIST)) \
: m_pHolder(0) \
{ \
this->add(ptr); \
} \
\
template <typename ObjectType> \
delegate(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
: m_pHolder(0) \
{ \
this->add(t, ptr); \
} \
\
template <typename ObjectType> \
delegate(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), \
bool needDelete = false) \
: m_pHolder(0) \
{ \
this->add(t, ptr, needDelete); \
} \
\
template <typename ObjectType> \
delegate(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
bool needDelete = false) \
: m_pHolder(0) \
{ \
this->add(t, ptr, needDelete); \
} \
\
template <typename FunctorType> \
explicit delegate(const FunctorType* pFunctor) \
: m_pHolder(0) \
{ \
this->add(pFunctor); \
} \
\
template <typename FunctorType> \
explicit delegate(FunctorType* pFunctor, bool needDelete = false) \
: m_pHolder(0) \
{ \
this->add(pFunctor, needDelete); \
} \
\
delegate(const SelfType& rhs) \
: local::ICallback<ReturnType(TYPE_LIST)>(rhs) \
, ThreadingModelType() \
{ \
copyFrom(rhs); \
} \
\
SelfType& operator=(const SelfType& rhs) \
{ \
if (this == &rhs) \
return *this; \
this->release(); \
copyFrom(rhs); \
return *this; \
} \
\
~delegate() \
{ \
release(); \
} \
\
void release() \
{ \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr = m_pHolder; \
while (ptr != 0) \
{ \
CallbackHolder* prev = ptr->prev; \
delete ptr->instance; \
delete ptr; \
ptr = prev; \
} \
m_pHolder = 0; \
} \
\
ReturnType operator()(TYPE_PARAM_LIST) \
{ \
return this->invoke(PARAM_LIST); \
} \
\
ReturnType invoke(TYPE_PARAM_LIST) const \
{ \
typename ThreadingModelType::Lock guard(*this); \
if (m_pHolder == 0) return ReturnType(); \
return m_pHolder->call(PARAM_LIST); \
} \
\
bool equals(const SuperType* pDelegate) const \
{ \
const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
if (pRhs == 0) return false; \
\
SelfType* temp = 0; \
const SelfType* pClone; \
cloneForComparison(pRhs, pClone, temp, typename ThreadingModelType::ThreadTag()); \
\
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr1 = m_pHolder; \
CallbackHolder* ptr2 = pClone->m_pHolder; \
while (ptr1 != 0 && ptr2 != 0) \
{ \
if (!ptr1->instance->equals(ptr2->instance)) \
break; \
ptr1 = ptr1->prev; \
ptr2 = ptr2->prev; \
} \
delete temp; \
return (ptr1 == 0 && ptr2 == 0); \
} \
\
SelfType* clone() const \
{ \
SelfType* pClone = new SelfType(); \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr = m_pHolder; \
CallbackHolder* pReverse = 0; \
while (ptr != 0) \
{ \
CallbackHolder* pHolder = new CallbackHolder(); \
pHolder->instance = ptr->instance->clone(); \
pHolder->prev = pReverse; \
pReverse = pHolder; \
ptr = ptr->prev; \
} \
\
CallbackHolder* prev = 0; \
while (pReverse != 0) \
{ \
CallbackHolder* next = pReverse->prev; \
pReverse->prev = prev; \
prev = pReverse; \
pReverse = next; \
} \
pClone->m_pHolder = prev; \
\
return pClone; \
} \
\
void add(ReturnType (*ptr)(TYPE_LIST)) \
{ \
SuperType* pNew = new local::NativeCallback<ReturnType(TYPE_LIST)>(ptr); \
this->addImpl(pNew); \
} \
\
template <typename ObjectType> \
void add(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)>(t, ptr); \
this->addImpl(pNew); \
} \
\
template <typename ObjectType> \
void add(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->addImpl(pNew); \
} \
\
template <typename ObjectType> \
void add(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->addImpl(pNew); \
} \
\
template <typename FunctorType> \
void add(FunctorType* pFunctor, bool needDelete = false) \
{ \
this->add(pFunctor, &FunctorType::operator(), needDelete); \
} \
\
template <typename FunctorType> \
void add(const FunctorType* pFunctor) \
{ \
this->add(pFunctor, &FunctorType::operator()); \
} \
\
void add(const SelfType& rhs) \
{ \
SelfType* pClone = rhs.clone(); \
this->addImpl(pClone); \
} \
\
void remove(ReturnType (*ptr)(TYPE_LIST)) \
{ \
SuperType* pNew = new local::NativeCallback<ReturnType(TYPE_LIST)>(ptr); \
this->removeImpl(pNew); \
} \
\
template <typename ObjectType> \
void remove(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)>(t, ptr); \
this->removeImpl(pNew); \
} \
\
template <typename ObjectType> \
void remove(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->removeImpl(pNew); \
} \
\
template <typename ObjectType> \
void remove(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->removeImpl(pNew); \
} \
\
template <typename FunctorType> \
void remove(FunctorType* pFunctor, bool needDelete = false) \
{ \
this->remove(pFunctor, &FunctorType::operator(), needDelete); \
} \
\
template <typename FunctorType> \
void remove(const FunctorType* pFunctor) \
{ \
this->remove(pFunctor, &FunctorType::operator()); \
} \
\
void remove(const SelfType& rhs) \
{ \
this->remove(rhs, typename ThreadingModelType::ThreadTag()); \
} \
\
private: \
void cloneForComparison(const SelfType* pRhs, const SelfType*& pClone, \
SelfType*& ptrForDelete, SingleThreadTag) const \
{ \
pClone = pRhs; \
ptrForDelete = 0; \
} \
\
void cloneForComparison(const SelfType* pRhs, const SelfType*& pClone, \
SelfType*& ptrForDelete, MultiThreadTag) const \
{ \
ptrForDelete = pRhs->clone(); \
pClone = ptrForDelete; \
} \
\
void copyFrom(const SelfType& rhs) \
{ \
SelfType* pClone = rhs.clone(); \
m_pHolder = pClone->m_pHolder; \
pClone->m_pHolder = 0; \
delete pClone; \
} \
\
void remove(const SelfType& rhs, SingleThreadTag) \
{ \
this->removeImpl(&rhs); \
} \
\
void remove(const SelfType& rhs, MultiThreadTag) \
{ \
this->removeImpl(rhs.clone()); \
} \
\
void addImpl(SuperType* pRhs) \
{ \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* pH = new CallbackHolder(); \
pH->instance = pRhs; \
pH->prev = m_pHolder; \
m_pHolder = pH; \
} \
\
void removeImpl(const SuperType* pRhs) \
{ \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr = m_pHolder; \
CallbackHolder* prev = 0; \
while (ptr != 0) \
{ \
if (ptr->instance->equals(pRhs)) \
{ \
if (prev == 0) m_pHolder = ptr->prev; \
else prev->prev = ptr->prev; \
delete ptr->instance; \
delete ptr; \
break; \
} \
prev = ptr; \
ptr = ptr->prev; \
} \
} \
\
void removeImpl(SuperType* pRhs) \
{ \
const SuperType* pConst = pRhs; \
this->removeImpl(pConst); \
delete pRhs; \
} \
\
private: \
CallbackHolder* m_pHolder; \
};
namespace local \
{ \
template <typename ReturnType TEMPLATE_LIST> \
class ICallback<ReturnType(TYPE_LIST)> \
{ \
typedef ICallback<ReturnType(TYPE_LIST)> SelfType; \
\
public: \
virtual ~ICallback() {} \
\
virtual ReturnType invoke(TYPE_LIST) const = 0; \
virtual bool equals(const SelfType* pDelegate) const = 0; \
virtual SelfType* clone() const = 0; \
}; \
\
template <typename ReturnType TEMPLATE_LIST> \
class NativeCallback<ReturnType(TYPE_LIST)> \
: public ICallback<ReturnType(TYPE_LIST)> \
{ \
typedef ICallback<ReturnType(TYPE_LIST)> SuperType; \
typedef NativeCallback<ReturnType(TYPE_LIST)> SelfType; \
typedef ReturnType (*FunctionPtr)(TYPE_LIST); \
\
public: \
explicit NativeCallback(FunctionPtr ptr) \
: m_handler(ptr) \
{ \
} \
\
NativeCallback(const SelfType& rhs) \
: ICallback<ReturnType(TYPE_LIST)>(rhs) \
, m_handler(rhs.m_handler) \
{ \
} \
\
ReturnType invoke(TYPE_PARAM_LIST) const \
{ \
return (*m_handler)(PARAM_LIST); \
} \
\
bool equals(const SuperType* pDelegate) const \
{ \
const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
if (pRhs == 0) return false; \
if (m_handler == pRhs->m_handler) return true; \
return false; \
} \
\
SelfType* clone() const \
{ \
return new SelfType(*this); \
} \
\
private: \
FunctionPtr m_handler; \
}; \
\
template <typename ObjectType, typename ReturnType TEMPLATE_LIST> \
class MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
: public ICallback<ReturnType(TYPE_LIST)> \
{ \
typedef ICallback<ReturnType(TYPE_LIST)> SuperType; \
typedef MemberCallback<ObjectType, ReturnType(TYPE_LIST)> SelfType; \
typedef ReturnType (ObjectType::*FunctionPtr)(TYPE_LIST); \
typedef ReturnType (ObjectType::*ConstFunctionPtr)(TYPE_LIST) const; \
\
enum { CONST_POINTER, NEED_DELETE, DONT_DELETE }; \
struct ObjectManager \
{ \
bool equals(const ObjectManager& rhs) \
{ \
return object.pObject == rhs.object.pObject; \
} \
\
union { ObjectType* pObject; const ObjectType* pConstObject; } object; \
int property; \
int refCount; \
}; \
\
public: \
MemberCallback(ObjectType* t, FunctionPtr ptr, bool needDelete = false) \
: m_isConstMemFunc(false) \
{ \
m_pObjectManager = new ObjectManager(); \
m_pObjectManager->object.pObject = t; \
m_pObjectManager->property = needDelete ? NEED_DELETE : DONT_DELETE; \
m_pObjectManager->refCount = 0; \
m_handler.ptr = ptr; \
incrementRefCount(); \
} \
\
MemberCallback(ObjectType* t, ConstFunctionPtr ptr, bool needDelete = false) \
: m_isConstMemFunc(true) \
{ \
m_pObjectManager = new ObjectManager(); \
m_pObjectManager->object.pObject = t; \
m_pObjectManager->property = needDelete ? NEED_DELETE : DONT_DELETE; \
m_pObjectManager->refCount = 0; \
m_handler.constPtr = ptr; \
incrementRefCount(); \
} \
\
MemberCallback(const ObjectType* t, ConstFunctionPtr ptr) \
: m_isConstMemFunc(true) \
{ \
m_pObjectManager = new ObjectManager(); \
m_pObjectManager->object.pConstObject = t; \
m_pObjectManager->property = CONST_POINTER; \
m_pObjectManager->refCount = 0; \
m_handler.constPtr = ptr; \
incrementRefCount(); \
} \
\
MemberCallback(const SelfType& rhs) \
: ICallback<ReturnType(TYPE_LIST)>(rhs) \
, m_pObjectManager(rhs.m_pObjectManager) \
, m_handler(rhs.m_handler) \
, m_isConstMemFunc(rhs.m_isConstMemFunc) \
{ \
incrementRefCount(); \
} \
\
virtual ~MemberCallback() \
{ \
decrementRefCount(); \
} \
\
MemberCallback& operator=(const SelfType& rhs) \
{ \
if (this == &rhs) \
return *this; \
decrementRefCount(); \
m_pObjectManager = rhs.m_pObjectManager; \
m_handler = rhs.m_handler; \
m_isConstMemFunc = rhs.m_isConstMemFunc; \
incrementRefCount(); \
return *this; \
} \
\
ReturnType invoke(TYPE_PARAM_LIST) const \
{ \
if (m_isConstMemFunc) \
{ \
if (m_pObjectManager->property == CONST_POINTER) \
return (m_pObjectManager->object.pConstObject->*(m_handler.constPtr))(PARAM_LIST); \
return (m_pObjectManager->object.pObject->*(m_handler.constPtr))(PARAM_LIST); \
} \
return (m_pObjectManager->object.pObject->*(m_handler.ptr))(PARAM_LIST); \
} \
\
bool equals(const SuperType* pDelegate) const \
{ \
const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
if (pRhs == 0) return false; \
if (m_pObjectManager->equals(*pRhs->m_pObjectManager) \
&& m_isConstMemFunc == pRhs->m_isConstMemFunc \
&& m_handler.ptr == pRhs->m_handler.ptr) \
return true; \
return false; \
} \
\
SelfType* clone() const \
{ \
return new SelfType(*this); \
} \
\
private: \
void incrementRefCount() \
{ \
++m_pObjectManager->refCount; \
} \
\
void decrementRefCount() \
{ \
if (--m_pObjectManager->refCount == 0) \
{ \
if (m_pObjectManager->property == NEED_DELETE) \
delete m_pObjectManager->object.pObject; \
\
delete m_pObjectManager; \
} \
} \
\
private: \
ObjectManager* m_pObjectManager; \
union { FunctionPtr ptr; ConstFunctionPtr constPtr; } m_handler; \
bool m_isConstMemFunc; \
}; \
} /* namespace local */ \
\
template <typename ReturnType TEMPLATE_LIST, typename LockType> \
class delegate<ReturnType(TYPE_LIST), LockType> \
: public local::ICallback<ReturnType(TYPE_LIST)> \
, public ThreadingModel<LockType> \
{ \
typedef local::ICallback<ReturnType(TYPE_LIST)> SuperType; \
typedef delegate<ReturnType(TYPE_LIST), LockType> SelfType; \
typedef ThreadingModel<LockType> ThreadingModelType; \
struct CallbackHolder \
{ \
SuperType* instance; \
CallbackHolder* prev; \
ReturnType call(TYPE_PARAM_LIST) \
{ \
if (prev != 0) prev->call(PARAM_LIST); \
return instance->invoke(PARAM_LIST); \
} \
}; \
\
public: \
delegate() : m_pHolder(0) {} \
\
explicit delegate(ReturnType (*ptr)(TYPE_LIST)) \
: m_pHolder(0) \
{ \
this->add(ptr); \
} \
\
template <typename ObjectType> \
delegate(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
: m_pHolder(0) \
{ \
this->add(t, ptr); \
} \
\
template <typename ObjectType> \
delegate(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), \
bool needDelete = false) \
: m_pHolder(0) \
{ \
this->add(t, ptr, needDelete); \
} \
\
template <typename ObjectType> \
delegate(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
bool needDelete = false) \
: m_pHolder(0) \
{ \
this->add(t, ptr, needDelete); \
} \
\
template <typename FunctorType> \
explicit delegate(const FunctorType* pFunctor) \
: m_pHolder(0) \
{ \
this->add(pFunctor); \
} \
\
template <typename FunctorType> \
explicit delegate(FunctorType* pFunctor, bool needDelete = false) \
: m_pHolder(0) \
{ \
this->add(pFunctor, needDelete); \
} \
\
delegate(const SelfType& rhs) \
: local::ICallback<ReturnType(TYPE_LIST)>(rhs) \
, ThreadingModelType() \
{ \
copyFrom(rhs); \
} \
\
SelfType& operator=(const SelfType& rhs) \
{ \
if (this == &rhs) \
return *this; \
this->release(); \
copyFrom(rhs); \
return *this; \
} \
\
~delegate() \
{ \
release(); \
} \
\
void release() \
{ \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr = m_pHolder; \
while (ptr != 0) \
{ \
CallbackHolder* prev = ptr->prev; \
delete ptr->instance; \
delete ptr; \
ptr = prev; \
} \
m_pHolder = 0; \
} \
\
ReturnType operator()(TYPE_PARAM_LIST) \
{ \
return this->invoke(PARAM_LIST); \
} \
\
ReturnType invoke(TYPE_PARAM_LIST) const \
{ \
typename ThreadingModelType::Lock guard(*this); \
if (m_pHolder == 0) return ReturnType(); \
return m_pHolder->call(PARAM_LIST); \
} \
\
bool equals(const SuperType* pDelegate) const \
{ \
const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
if (pRhs == 0) return false; \
\
SelfType* temp = 0; \
const SelfType* pClone; \
cloneForComparison(pRhs, pClone, temp, typename ThreadingModelType::ThreadTag()); \
\
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr1 = m_pHolder; \
CallbackHolder* ptr2 = pClone->m_pHolder; \
while (ptr1 != 0 && ptr2 != 0) \
{ \
if (!ptr1->instance->equals(ptr2->instance)) \
break; \
ptr1 = ptr1->prev; \
ptr2 = ptr2->prev; \
} \
delete temp; \
return (ptr1 == 0 && ptr2 == 0); \
} \
\
SelfType* clone() const \
{ \
SelfType* pClone = new SelfType(); \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr = m_pHolder; \
CallbackHolder* pReverse = 0; \
while (ptr != 0) \
{ \
CallbackHolder* pHolder = new CallbackHolder(); \
pHolder->instance = ptr->instance->clone(); \
pHolder->prev = pReverse; \
pReverse = pHolder; \
ptr = ptr->prev; \
} \
\
CallbackHolder* prev = 0; \
while (pReverse != 0) \
{ \
CallbackHolder* next = pReverse->prev; \
pReverse->prev = prev; \
prev = pReverse; \
pReverse = next; \
} \
pClone->m_pHolder = prev; \
\
return pClone; \
} \
\
void add(ReturnType (*ptr)(TYPE_LIST)) \
{ \
SuperType* pNew = new local::NativeCallback<ReturnType(TYPE_LIST)>(ptr); \
this->addImpl(pNew); \
} \
\
template <typename ObjectType> \
void add(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)>(t, ptr); \
this->addImpl(pNew); \
} \
\
template <typename ObjectType> \
void add(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->addImpl(pNew); \
} \
\
template <typename ObjectType> \
void add(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->addImpl(pNew); \
} \
\
template <typename FunctorType> \
void add(FunctorType* pFunctor, bool needDelete = false) \
{ \
this->add(pFunctor, &FunctorType::operator(), needDelete); \
} \
\
template <typename FunctorType> \
void add(const FunctorType* pFunctor) \
{ \
this->add(pFunctor, &FunctorType::operator()); \
} \
\
void add(const SelfType& rhs) \
{ \
SelfType* pClone = rhs.clone(); \
this->addImpl(pClone); \
} \
\
void remove(ReturnType (*ptr)(TYPE_LIST)) \
{ \
SuperType* pNew = new local::NativeCallback<ReturnType(TYPE_LIST)>(ptr); \
this->removeImpl(pNew); \
} \
\
template <typename ObjectType> \
void remove(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)>(t, ptr); \
this->removeImpl(pNew); \
} \
\
template <typename ObjectType> \
void remove(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->removeImpl(pNew); \
} \
\
template <typename ObjectType> \
void remove(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
bool needDelete = false) \
{ \
SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
(t, ptr, needDelete); \
this->removeImpl(pNew); \
} \
\
template <typename FunctorType> \
void remove(FunctorType* pFunctor, bool needDelete = false) \
{ \
this->remove(pFunctor, &FunctorType::operator(), needDelete); \
} \
\
template <typename FunctorType> \
void remove(const FunctorType* pFunctor) \
{ \
this->remove(pFunctor, &FunctorType::operator()); \
} \
\
void remove(const SelfType& rhs) \
{ \
this->remove(rhs, typename ThreadingModelType::ThreadTag()); \
} \
\
private: \
void cloneForComparison(const SelfType* pRhs, const SelfType*& pClone, \
SelfType*& ptrForDelete, SingleThreadTag) const \
{ \
pClone = pRhs; \
ptrForDelete = 0; \
} \
\
void cloneForComparison(const SelfType* pRhs, const SelfType*& pClone, \
SelfType*& ptrForDelete, MultiThreadTag) const \
{ \
ptrForDelete = pRhs->clone(); \
pClone = ptrForDelete; \
} \
\
void copyFrom(const SelfType& rhs) \
{ \
SelfType* pClone = rhs.clone(); \
m_pHolder = pClone->m_pHolder; \
pClone->m_pHolder = 0; \
delete pClone; \
} \
\
void remove(const SelfType& rhs, SingleThreadTag) \
{ \
this->removeImpl(&rhs); \
} \
\
void remove(const SelfType& rhs, MultiThreadTag) \
{ \
this->removeImpl(rhs.clone()); \
} \
\
void addImpl(SuperType* pRhs) \
{ \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* pH = new CallbackHolder(); \
pH->instance = pRhs; \
pH->prev = m_pHolder; \
m_pHolder = pH; \
} \
\
void removeImpl(const SuperType* pRhs) \
{ \
typename ThreadingModelType::Lock guard(*this); \
CallbackHolder* ptr = m_pHolder; \
CallbackHolder* prev = 0; \
while (ptr != 0) \
{ \
if (ptr->instance->equals(pRhs)) \
{ \
if (prev == 0) m_pHolder = ptr->prev; \
else prev->prev = ptr->prev; \
delete ptr->instance; \
delete ptr; \
break; \
} \
prev = ptr; \
ptr = ptr->prev; \
} \
} \
\
void removeImpl(SuperType* pRhs) \
{ \
const SuperType* pConst = pRhs; \
this->removeImpl(pConst); \
delete pRhs; \
} \
\
private: \
CallbackHolder* m_pHolder; \
};
#define TEMPLATE_LIST_0
#define TEMPLATE_LIST_1 TEMPLATE_LIST_0, typename T0
#define TEMPLATE_LIST_2 TEMPLATE_LIST_1, typename T1
#define TEMPLATE_LIST_3 TEMPLATE_LIST_2, typename T2
#define TEMPLATE_LIST_4 TEMPLATE_LIST_3, typename T3
#define TEMPLATE_LIST_5 TEMPLATE_LIST_4, typename T4
#define TEMPLATE_LIST_6 TEMPLATE_LIST_5, typename T5
#define TEMPLATE_LIST_1 TEMPLATE_LIST_0, typename T0
#define TEMPLATE_LIST_2 TEMPLATE_LIST_1, typename T1
#define TEMPLATE_LIST_3 TEMPLATE_LIST_2, typename T2
#define TEMPLATE_LIST_4 TEMPLATE_LIST_3, typename T3
#define TEMPLATE_LIST_5 TEMPLATE_LIST_4, typename T4
#define TEMPLATE_LIST_6 TEMPLATE_LIST_5, typename T5
#define TYPE_LIST_0
#define TYPE_LIST_1 T0
#define TYPE_LIST_2 TYPE_LIST_1, T1
#define TYPE_LIST_3 TYPE_LIST_2, T2
#define TYPE_LIST_4 TYPE_LIST_3, T3
#define TYPE_LIST_5 TYPE_LIST_4, T4
#define TYPE_LIST_6 TYPE_LIST_5, T5
#define TYPE_LIST_1 T0
#define TYPE_LIST_2 TYPE_LIST_1, T1
#define TYPE_LIST_3 TYPE_LIST_2, T2
#define TYPE_LIST_4 TYPE_LIST_3, T3
#define TYPE_LIST_5 TYPE_LIST_4, T4
#define TYPE_LIST_6 TYPE_LIST_5, T5
#define TYPE_PARAM_LIST_0
#define TYPE_PARAM_LIST_1 T0 t0
#define TYPE_PARAM_LIST_2 TYPE_PARAM_LIST_1, T1 t1
#define TYPE_PARAM_LIST_3 TYPE_PARAM_LIST_2, T2 t2
#define TYPE_PARAM_LIST_4 TYPE_PARAM_LIST_3, T3 t3
#define TYPE_PARAM_LIST_5 TYPE_PARAM_LIST_4, T4 t4
#define TYPE_PARAM_LIST_6 TYPE_PARAM_LIST_5, T5 t5
#define TYPE_PARAM_LIST_1 T0 t0
#define TYPE_PARAM_LIST_2 TYPE_PARAM_LIST_1, T1 t1
#define TYPE_PARAM_LIST_3 TYPE_PARAM_LIST_2, T2 t2
#define TYPE_PARAM_LIST_4 TYPE_PARAM_LIST_3, T3 t3
#define TYPE_PARAM_LIST_5 TYPE_PARAM_LIST_4, T4 t4
#define TYPE_PARAM_LIST_6 TYPE_PARAM_LIST_5, T5 t5
#define PARAM_LIST_0
#define PARAM_LIST_1 t0
#define PARAM_LIST_2 PARAM_LIST_1, t1
#define PARAM_LIST_3 PARAM_LIST_2, t2
#define PARAM_LIST_4 PARAM_LIST_3, t3
#define PARAM_LIST_5 PARAM_LIST_4, t4
#define PARAM_LIST_6 PARAM_LIST_5, t5
#define PARAM_LIST_1 t0
#define PARAM_LIST_2 PARAM_LIST_1, t1
#define PARAM_LIST_3 PARAM_LIST_2, t2
#define PARAM_LIST_4 PARAM_LIST_3, t3
#define PARAM_LIST_5 PARAM_LIST_4, t4
#define PARAM_LIST_6 PARAM_LIST_5, t5
DELEGATE_GENERATOR(TEMPLATE_LIST_0, TYPE_LIST_0, TYPE_PARAM_LIST_0,
PARAM_LIST_0)
DELEGATE_GENERATOR(TEMPLATE_LIST_1, TYPE_LIST_1, TYPE_PARAM_LIST_1, PARAM_LIST_1)
DELEGATE_GENERATOR(TEMPLATE_LIST_2, TYPE_LIST_2, TYPE_PARAM_LIST_2, PARAM_LIST_2)
DELEGATE_GENERATOR(TEMPLATE_LIST_3, TYPE_LIST_3, TYPE_PARAM_LIST_3, PARAM_LIST_3)
DELEGATE_GENERATOR(TEMPLATE_LIST_4, TYPE_LIST_4, TYPE_PARAM_LIST_4, PARAM_LIST_4)
DELEGATE_GENERATOR(TEMPLATE_LIST_5, TYPE_LIST_5, TYPE_PARAM_LIST_5, PARAM_LIST_5)
DELEGATE_GENERATOR(TEMPLATE_LIST_6, TYPE_LIST_6, TYPE_PARAM_LIST_6, PARAM_LIST_6)
DELEGATE_GENERATOR(TEMPLATE_LIST_1, TYPE_LIST_1, TYPE_PARAM_LIST_1, PARAM_LIST_1)
DELEGATE_GENERATOR(TEMPLATE_LIST_2, TYPE_LIST_2, TYPE_PARAM_LIST_2, PARAM_LIST_2)
DELEGATE_GENERATOR(TEMPLATE_LIST_3, TYPE_LIST_3, TYPE_PARAM_LIST_3, PARAM_LIST_3)
DELEGATE_GENERATOR(TEMPLATE_LIST_4, TYPE_LIST_4, TYPE_PARAM_LIST_4, PARAM_LIST_4)
DELEGATE_GENERATOR(TEMPLATE_LIST_5, TYPE_LIST_5, TYPE_PARAM_LIST_5, PARAM_LIST_5)
DELEGATE_GENERATOR(TEMPLATE_LIST_6, TYPE_LIST_6, TYPE_PARAM_LIST_6, PARAM_LIST_6)
// remove the macros
#undef DELEGATE_GENERATOR
#undef TEMPLATE_LIST_0
#undef TEMPLATE_LIST_1
#undef TEMPLATE_LIST_2
#undef TEMPLATE_LIST_3
#undef TEMPLATE_LIST_4
#undef TEMPLATE_LIST_5
#undef TEMPLATE_LIST_6
#undef DELEGATE_GENERATOR
#undef TEMPLATE_LIST_0
#undef TEMPLATE_LIST_1
#undef TEMPLATE_LIST_2
#undef TEMPLATE_LIST_3
#undef TEMPLATE_LIST_4
#undef TEMPLATE_LIST_5
#undef TEMPLATE_LIST_6
#undef TYPE_LIST_0
#undef TYPE_LIST_1
#undef TYPE_LIST_2
#undef TYPE_LIST_3
#undef TYPE_LIST_4
#undef TYPE_LIST_5
#undef TYPE_LIST_6
#undef TYPE_LIST_1
#undef TYPE_LIST_2
#undef TYPE_LIST_3
#undef TYPE_LIST_4
#undef TYPE_LIST_5
#undef TYPE_LIST_6
#undef TYPE_PARAM_LIST_0
#undef TYPE_PARAM_LIST_1
#undef TYPE_PARAM_LIST_2
#undef TYPE_PARAM_LIST_3
#undef TYPE_PARAM_LIST_4
#undef TYPE_PARAM_LIST_5
#undef TYPE_PARAM_LIST_6
#undef TYPE_PARAM_LIST_1
#undef TYPE_PARAM_LIST_2
#undef TYPE_PARAM_LIST_3
#undef TYPE_PARAM_LIST_4
#undef TYPE_PARAM_LIST_5
#undef TYPE_PARAM_LIST_6
#undef PARAM_LIST_0
#undef PARAM_LIST_1
#undef PARAM_LIST_2
#undef PARAM_LIST_3
#undef PARAM_LIST_4
#undef PARAM_LIST_5
#undef PARAM_LIST_6
} // namespace
#undef PARAM_LIST_1
#undef PARAM_LIST_2
#undef PARAM_LIST_3
#undef PARAM_LIST_4
#undef PARAM_LIST_5
#undef PARAM_LIST_6
} // namespace
#endif // WAN_DELEGATE_H
threadingmodel.h
#ifndef WAN_THREADINGMODEL_H
#define WAN_THREADINGMODEL_H
/**
* @author Kevin Wan <wanjunfeng@gmail.com>
* @date 12/30/2005
* Copyright (C) Kevin Wan
*/
namespace wan
{
struct SingleThreadTag {};
struct MultiThreadTag {};
template <typename LockType>
class ThreadingModel
{
public:
typedef MultiThreadTag ThreadTag;
class Lock
{
Lock(const Lock&);
void operator=(const Lock&);
public:
explicit Lock(const ThreadingModel& host)
: m_host(host)
{
m_host.m_mutex.lock();
}
~Lock()
{
m_host.m_mutex.unlock();
}
private:
const ThreadingModel& m_host;
};
friend class Lock;
ThreadingModel() {}
private:
ThreadingModel(const ThreadingModel&);
ThreadingModel& operator=(const ThreadingModel&);
private:
mutable LockType m_mutex;
};
template <>
class ThreadingModel<void>
{
public:
typedef SingleThreadTag ThreadTag;
struct Lock
{
explicit Lock(const ThreadingModel&) {}
};
ThreadingModel() {}
private:
ThreadingModel(const ThreadingModel&);
ThreadingModel& operator=(const ThreadingModel&);
};
} // namespace
#endif // WAN_THREADINGMODEL_H
example.cc
#include <stdio.h>
#include "delegate.h"
const char* bar = "##########################################";
void native_func(int value)
{
printf("%s\n", bar);
printf("native function, value = %d\n", value);
}
class Object
{
public:
static void static_member_func(int value)
{
printf("%s\n", bar);
printf("static member function, value = %d\n", value);
}
void non_const_member_func(int value)
{
printf("%s\n", bar);
printf("non-const member function, value = %d\n", value);
}
void const_member_func(int value) const
{
printf("%s\n", bar);
printf("const member function, value = %d\n", value);
}
};
class Functor
{
public:
void operator()(int value)
{
printf("%s\n", bar);
printf("non-const functor, value = %d\n", value);
}
};
class ConstFunctor
{
public:
void operator()(int value) const
{
printf("%s\n", bar);
printf("const functor, value = %d\n", value);
}
};
int main()
{
typedef wan::delegate<void(int)> MyDelegate;
Object obj;
Functor functor;
ConstFunctor constFunctor;
MyDelegate dele;
dele.add(&native_func);
dele.add(&Object::static_member_func);
dele.add(&obj, &Object::non_const_member_func);
dele.add(&obj, &Object::const_member_func);
dele.add(&functor);
dele.add(&constFunctor);
dele(111);
printf("%s\n", bar);
printf("\n\nafter remove operations\n\n");
dele.remove(&native_func);
dele.remove(&obj, &Object::non_const_member_func);
dele(222);
printf("%s\n", bar);
printf("\n\nadd delegate object to delegate object\n\n");
MyDelegate temp;
temp.add(&native_func);
temp.add(&obj, &Object::non_const_member_func);
dele.add(&temp);
dele(333);
printf("%s\n", bar);
}
test.cc
#include <stdio.h>
#include "delegate.h"
// #include "mutex.h"
struct DummyLock
{
void lock() {}
void unlock() {}
};
void print_hello()
{
printf("print_hello\n");
}
void print_world()
{
printf("print_world\n");
}
class Object
{
public:
Object() { printf("Object::Object\n"); }
~Object() { printf("Object::~Object\n"); }
void print() const
{
printf("in Object::print\n");
}
void test() const
{
wan::delegate<void()> d;
d.add(this, &Object::print);
d();
}
};
class Functor
{
public:
void operator()() const
{
printf("in Functor::operator() const\n");
}
};
int main()
{
{
wan::delegate<void(), DummyLock> d;
d.add(&print_hello);
d.add(&print_world);
if (d.equals(&d))
printf("the same\n");
else
printf("not the same\n");
printf("\n");
wan::delegate<void(), DummyLock>* pd = d.clone();
if (d.equals(pd))
printf("the same\n");
else
printf("not the same\n");
delete pd;
printf("\n");
d();
wan::delegate<void(), DummyLock> d1(d);
printf("%u\n", sizeof(d));
d.add(d);
d();
printf("\n");
d.remove(d1);
d();
}
/*
{
wan::delegate<void(), Mutex> d;
d.add(&print_hello);
printf("%u\n", sizeof(d));
}
*/
{
wan::delegate<void()> d;
d.add(new Object(), &Object::print, true);
d();
wan::delegate<void()> d1(d);
wan::delegate<void()>* d2 = d.clone();
d1();
(*d2)();
delete d2;
}
{
Object obj;
obj.test();
}
{
wan::delegate<void()> d;
d.add(new Functor(), true);
d();
}
}
threadingmodel.h
#ifndef WAN_THREADINGMODEL_H
#define WAN_THREADINGMODEL_H
/**
* @author Kevin Wan <wanjunfeng@gmail.com>
* @date 12/30/2005
* Copyright (C) Kevin Wan
*/
namespace wan
{
struct SingleThreadTag {};
struct MultiThreadTag {};
template <typename LockType>
class ThreadingModel
{
public:
typedef MultiThreadTag ThreadTag;
class Lock
{
Lock(const Lock&);
void operator=(const Lock&);
public:
explicit Lock(const ThreadingModel& host)
: m_host(host)
{
m_host.m_mutex.lock();
}
~Lock()
{
m_host.m_mutex.unlock();
}
private:
const ThreadingModel& m_host;
};
friend class Lock;
ThreadingModel() {}
private:
ThreadingModel(const ThreadingModel&);
ThreadingModel& operator=(const ThreadingModel&);
private:
mutable LockType m_mutex;
};
template <>
class ThreadingModel<void>
{
public:
typedef SingleThreadTag ThreadTag;
struct Lock
{
explicit Lock(const ThreadingModel&) {}
};
ThreadingModel() {}
private:
ThreadingModel(const ThreadingModel&);
ThreadingModel& operator=(const ThreadingModel&);
};
} // namespace
#endif // WAN_THREADINGMODEL_H
example.cc
#include <stdio.h>
#include "delegate.h"
const char* bar = "##########################################";
void native_func(int value)
{
printf("%s\n", bar);
printf("native function, value = %d\n", value);
}
class Object
{
public:
static void static_member_func(int value)
{
printf("%s\n", bar);
printf("static member function, value = %d\n", value);
}
void non_const_member_func(int value)
{
printf("%s\n", bar);
printf("non-const member function, value = %d\n", value);
}
void const_member_func(int value) const
{
printf("%s\n", bar);
printf("const member function, value = %d\n", value);
}
};
class Functor
{
public:
void operator()(int value)
{
printf("%s\n", bar);
printf("non-const functor, value = %d\n", value);
}
};
class ConstFunctor
{
public:
void operator()(int value) const
{
printf("%s\n", bar);
printf("const functor, value = %d\n", value);
}
};
int main()
{
typedef wan::delegate<void(int)> MyDelegate;
Object obj;
Functor functor;
ConstFunctor constFunctor;
MyDelegate dele;
dele.add(&native_func);
dele.add(&Object::static_member_func);
dele.add(&obj, &Object::non_const_member_func);
dele.add(&obj, &Object::const_member_func);
dele.add(&functor);
dele.add(&constFunctor);
dele(111);
printf("%s\n", bar);
printf("\n\nafter remove operations\n\n");
dele.remove(&native_func);
dele.remove(&obj, &Object::non_const_member_func);
dele(222);
printf("%s\n", bar);
printf("\n\nadd delegate object to delegate object\n\n");
MyDelegate temp;
temp.add(&native_func);
temp.add(&obj, &Object::non_const_member_func);
dele.add(&temp);
dele(333);
printf("%s\n", bar);
}
test.cc
#include <stdio.h>
#include "delegate.h"
// #include "mutex.h"
struct DummyLock
{
void lock() {}
void unlock() {}
};
void print_hello()
{
printf("print_hello\n");
}
void print_world()
{
printf("print_world\n");
}
class Object
{
public:
Object() { printf("Object::Object\n"); }
~Object() { printf("Object::~Object\n"); }
void print() const
{
printf("in Object::print\n");
}
void test() const
{
wan::delegate<void()> d;
d.add(this, &Object::print);
d();
}
};
class Functor
{
public:
void operator()() const
{
printf("in Functor::operator() const\n");
}
};
int main()
{
{
wan::delegate<void(), DummyLock> d;
d.add(&print_hello);
d.add(&print_world);
if (d.equals(&d))
printf("the same\n");
else
printf("not the same\n");
printf("\n");
wan::delegate<void(), DummyLock>* pd = d.clone();
if (d.equals(pd))
printf("the same\n");
else
printf("not the same\n");
delete pd;
printf("\n");
d();
wan::delegate<void(), DummyLock> d1(d);
printf("%u\n", sizeof(d));
d.add(d);
d();
printf("\n");
d.remove(d1);
d();
}
/*
{
wan::delegate<void(), Mutex> d;
d.add(&print_hello);
printf("%u\n", sizeof(d));
}
*/
{
wan::delegate<void()> d;
d.add(new Object(), &Object::print, true);
d();
wan::delegate<void()> d1(d);
wan::delegate<void()>* d2 = d.clone();
d1();
(*d2)();
delete d2;
}
{
Object obj;
obj.test();
}
{
wan::delegate<void()> d;
d.add(new Functor(), true);
d();
}
}