//instEvent.h
#ifndef INST_EVENT_H
#define INST_EVENT_H
#include <instDefines.h>
#include <instArray.h>
#include <instList.h>
namespace inst
{
template <typename T> val_class _EventMgr // 必须用用SmartPtr保持强引用,而Peek()之后引用就会解除引用
{
public:
typedef void (__obj:: *EVENTFUNC)(IDynamic *,const void *);
typedef struct _EVENTCALL
{
void *pObjAddr; // thiscallのために用いられる。
SmartPtr<IDynamic> pObjRoot; // 参照回数計測のために用いられる。Peek()之后引用就会解除
SmartPtr<IDynamic> pSender; // Peek()之后引用就会解除
EVENTFUNC pFunc;
const void *pArgsAddr;
SmartPtr<const IDynamic> pArgsRoot;
Bool operator ==(const _EVENTCALL &o)
{
return pObjAddr==o.pObjAddr && pObjRoot==o.pObjRoot && pSender==o.pSender &&
pFunc==o.pFunc && pArgsAddr==o.pArgsAddr && pArgsRoot==o.pArgsRoot;
}
Bool operator !=(const _EVENTCALL &o)
{
return pObjAddr!=o.pObjAddr || pObjRoot!=o.pObjRoot || pSender!=o.pSender ||
pFunc!=o.pFunc || pArgsAddr!=o.pArgsAddr || pArgsRoot!=o.pArgsRoot;
}
}EVENTCALL;
private:
static List<EVENTCALL> s_EventCalls;
static Int32 s_MaxSize;
public:
static void Post(const EVENTCALL &ec)
{
INST_ASSERT(ec.pObjAddr);
INST_ASSERT(ec.pObjRoot);
INST_ASSERT(ec.pSender);
INST_ASSERT(ec.pFunc);
INST_ASSERT(ec.pArgsAddr);
INST_ASSERT(ec.pArgsRoot);
s_EventCalls.Add(ec); // Peek()之后强引用们就会解除
if( s_MaxSize>0 && s_EventCalls.Count()>s_MaxSize ) s_EventCalls.Remove(0);
}
public:
static Bool Peek()
{
if(s_EventCalls.Count()==0) return False;
EVENTCALL ec = s_EventCalls.GetRemove(0);
INST_ASSERT(ec.pObjAddr);
INST_ASSERT(ec.pObjRoot);
INST_ASSERT(ec.pSender);
INST_ASSERT(ec.pFunc);
INST_ASSERT(ec.pArgsAddr);
INST_ASSERT(ec.pArgsRoot);
INST_THISCALLBACK(ec.pObjAddr, ec.pFunc, void, (const IDynamic *,const void *), (ec.pSender,ec.pArgsAddr));
return True;
}
static void PeekAll()
{
while(Peek()){};
}
static void SetMaxSize(Int32 maxsize){ s_MaxSize = MAX(maxsize,1); } // 最小为1
};
typedef _EventMgr<void> CEventMgr;
#if _MSC_VER<1400
template <class T> List<_EventMgr<T>::EVENTCALL> _EventMgr<T>::s_EventCalls;
template <class T> Int32 _EventMgr<T>::s_MaxSize = 0; // 0 - no limit
#else
List<CEventMgr::EVENTCALL> CEventMgr::s_EventCalls;
Int32 CEventMgr::s_MaxSize = 0; // 0 - no limit
#endif
template <class A> val_class Event
{
private:
typedef struct _EVENTHANDLER
{
void *pObjAddr;
IDynamic *pObjRoot; // 这里是weak ptr!这里的IDynamic不是用来增加RefCount的,而是等到RaiseEvent的时候传给EventMgr(他要增加RefCount)。 注意,不用了的话,应当RemoveHandler.
CEventMgr::EVENTFUNC pFunc; // ...某个FormXXX在destructing的时候,只允许RemoveHandler(自己的),因为控件和他的Handler可能正在别处被使用
Bool operator ==(const _EVENTHANDLER &o)const{ return pObjAddr==o.pObjAddr && pObjRoot==o.pObjRoot && pFunc==o.pFunc; }
Bool operator !=(const _EVENTHANDLER &o)const{ return pObjAddr!=o.pObjAddr || pObjRoot!=o.pObjRoot || pFunc!=o.pFunc; }
}EVENTHANDLER;
Array<EVENTHANDLER> m_EventHandlers;
public:
Event():m_EventHandlers(){}
#if _MSC_VER < 1400
template <class O,class F> void AddHandler(O *obj,F func)
#else
template <class O> void AddHandler(O *obj,void (O:: *func)(IDynamic *,const A *))
#endif
{
INST_ASSERT(obj);
INST_ASSERT(func);
EVENTHANDLER eh;
eh.pObjAddr = reinterpret_cast<void *>(obj);
eh.pObjRoot = static_cast<IDynamic *>(obj);
eh.pFunc = union_cast<CEventMgr::EVENTFUNC>(func);
if(m_EventHandlers.Find(eh))return;
m_EventHandlers.Add(eh);
}
#if _MSC_VER < 1400
template <class O,class F> void RemoveHandler(O *obj,F func)
#else
template <class O> void RemoveHandler(O *obj,void (O:: *func)(IDynamic *,const A *))
#endif
{
INST_ASSERT(obj);
INST_ASSERT(func);
EVENTHANDLER eh;
eh.pObjAddr = reinterpret_cast<void *>(obj);
eh.pObjRoot = obj; // 自动转换为 SmartPtr<IDynamic *> 为安全绝不可以写强制转换!
eh.pFunc = union_cast<CEventMgr::EVENTFUNC>(func);
m_EventHandlers.FindRemove(eh);
}
void PostEvent(IDynamic *sender,const A *args) // 允许用户直接传入 new Args~~用户没必要AddRef/Release~~
{
INST_ASSERT(sender);
INST_ASSERT(args);
CEventMgr::EVENTCALL ec;
ec.pSender = sender; // SmartPtr,但是,这里是Stack,绝对不会发生自引用或循环引用!
ec.pArgsAddr = reinterpret_cast<const void *>(args);
ec.pArgsRoot = static_cast<const IDynamic *>(args);
// 必须要对这些强引用AddRef/Release。否则,如果用户是直接new的话,那么永远不会被删除...
if(m_EventHandlers.Count()==0) return; // ...上面的ec.pArgsRoot是SmartPtr,所以这里可以直接安全return
EVENTHANDLER eh;
for(Int32 i=0; i<m_EventHandlers.Count(); i++)
{
eh=m_EventHandlers.Get(i);
ec.pObjAddr = eh.pObjAddr;
ec.pObjRoot = eh.pObjRoot;
ec.pFunc = eh.pFunc;
CEventMgr::Post(ec); // RefCount of Args and Obj, will be added here
}
}
};
class CNullEventArgs:virtual public IDynamic
{
INST_DYNAMIC1(L"inst.CNullEventArgs");
protected:
~CNullEventArgs(){}
};
typedef Event<CNullEventArgs> CSimpleEvent;
class CGlobalEventSender:virtual public IDynamic // 按要求sender不能为null,所以全局Event用这个类的实例
{
INST_DYNAMIC1(L"inst.CGlobalEventSender");
protected:
~CGlobalEventSender(){}
};
// a sample:
//void Form_MouseDown(IDynamic *sender, const CMouseEventArgs *e);
}//end of namespace inst
#endif