|

楼主 |
发表于 2009-10-26 16:27:00
|
显示全部楼层
Re:最近突然感觉自己很强。
assent 事件处理
class SERVER_DECL EventableObject
{
//申明两个友元类
friend class EventMgr;
friend class EventableObjectHolder;
protected:
//删除一个事件
void event_RemoveEvents();
//删除某类事件
void event_RemoveEvents(uint32 EventType);
void event_ModifyTimeLeft(uint32 EventType, uint32 TimeLeft,bool unconditioned=false);
void event_ModifyTime(uint32 EventType, uint32 Time);
void event_ModifyTimeAndTimeLeft(uint32 EventType, uint32 Time);
bool event_HasEvent(uint32 EventType);
void event_RemoveByPointer(TimedEvent * ev);
//得到事件的场景ID
ASCENT_INLINE int32 event_GetCurrentInstanceId() { return m_event_Instanceid; }
public:
uint32 event_GetEventPeriod(uint32 EventType);
// Public methods
EventableObject();
virtual ~EventableObject();
ASCENT_INLINE bool event_HasEvents() { return m_events.size() > 0 ? true : false; }
//增加一个事件
void event_AddEvent(TimedEvent * ptr);
//重置所有事件
void event_Relocate();
// this func needs to be implemented by all eventable classes. use it to retreive the instance
// id that it needs to attach itself to.
virtual int32 event_GetInstanceID() { return -1; }
protected:
int32 m_event_Instanceid;
FastMutex m_lock;
EventMap m_events;
EventableObjectHolder * m_holder;
};
//EventMap被定义为typedef multimap<uint32, TimedEvent*> EventMap;因为同一类型的事件可能有许多种,至于multimap处理效率怎么样呢
我还是倾向于用map<int list<TimedEvent *>> 这样操作起来比较简单。或者可以用一个优先级别的list;
增加事件的时候
void EventableObject::event_AddEvent(TimedEvent * ptr)
{
m_lock.Acquire();
if(!m_holder)
{
m_event_Instanceid = event_GetInstanceID();
m_holder = sEventMgr.GetEventHolder(m_event_Instanceid);
}
ptr->IncRef();
ptr->instanceId = m_event_Instanceid;
pair<uint32,TimedEvent*> p(ptr->eventType, ptr);
m_events.insert( p );
m_lock.Release();
/* Add to event manager */
if(!m_holder)
{
/* relocate to -1 eventholder :/ */
m_event_Instanceid = -1;
m_holder = sEventMgr.GetEventHolder(m_event_Instanceid);
ASSERT(m_holder);
}
m_holder->AddEvent(ptr);
}
把事件插入到m_events映射列表里和m_holder->AddEvent(ptr)事件钩子,事件钩子从那里来的呢,m_holder = sEventMgr.GetEventHolder(m_event_Instanceid);
接下来看看m_holder,sEventMgr.
class EventableObjectHolder
{
public:
EventableObjectHolder(int32 instance_id);
~EventableObjectHolder();
void Update(uint32 time_difference);
void AddEvent(TimedEvent * ev);
void AddObject(EventableObject * obj);
ASCENT_INLINE uint32 GetInstanceID() { return mInstanceId; }
protected:
int32 mInstanceId;
Mutex m_lock;
EventList m_events;
Mutex m_insertPoolLock;
typedef list<TimedEvent*> InsertableQueue;
InsertableQueue m_insertPool;
};
这里有两个事件列表,这个是为了处理的时候,避免资源竞争,用空间换时间的一个策略。这样我们我们的线程update遍历处理m_events时,在其他线程处理的时
其他场景线程也可以给我们的场景处理线程压入事件。
类比较简单。只有增加事件,处理事件,需要说明的所有这些都是基于场景的int32 mInstanceId,对象加入事件
void EventableObject::event_AddEvent(TimedEvent * ptr)
{
m_lock.Acquire();
if(!m_holder)
{
m_event_Instanceid = event_GetInstanceID();
m_holder = sEventMgr.GetEventHolder(m_event_Instanceid);
}
ptr->IncRef();
ptr->instanceId = m_event_Instanceid;
pair<uint32,TimedEvent*> p(ptr->eventType, ptr);
m_events.insert( p );
m_lock.Release();
/* Add to event manager */
if(!m_holder)
{
/* relocate to -1 eventholder :/ */
m_event_Instanceid = -1;
m_holder = sEventMgr.GetEventHolder(m_event_Instanceid);
ASSERT(m_holder);
}
m_holder->AddEvent(ptr);
}
上边函数的代码,说明事件的场景ID,事件钩子EventableObjectHolder 场景ID.因为所有的事件都是在场景线程里处理的。
if(!m_holder)
{
m_event_Instanceid = event_GetInstanceID();
m_holder = sEventMgr.GetEventHolder(m_event_Instanceid);
}
ptr->IncRef();
ptr->instanceId = m_event_Instanceid;
pair<uint32,TimedEvent*> p(ptr->eventType, ptr);
事件对象,其实就是处理事件的参数,函数指针的集合
struct SERVER_DECL TimedEvent
{
TimedEvent(void* object, CallbackBase* callback, uint32 type, time_t time, uint32 repeat, uint32 flags) :
obj(object), cb(callback), eventType(type), eventFlag(flags), msTime(time), currTime(time), repeats(repeat), deleted(false),ref(0) {}
//
这两个想到与对象成员函数
void *obj;
CallbackBase *cb;
//一下控制事件的生命周期与执行的
//事件类型
uint32 eventType;
//标记
uint16 eventFlag;
//时间
time_t msTime;
//当前时间
time_t currTime;
//重复执行的次数
uint16 repeats;
//是否删除
bool deleted;
//事件发生场景环境
int instanceId;
//引用计数
volatile long ref;
static TimedEvent * Allocate(void* object, CallbackBase* callback, uint32 flags, time_t time, uint32 repeat);
#ifdef WIN32
void DecRef()
{
InterlockedDecrement(&ref);
if(ref <= 0)
{
delete cb;
delete this;
}
}
void IncRef() { InterlockedIncrement(&ref); }
#else
/* burlex: if anyone knows how to do the equivilent of InterlockedIncrement/Decrement on linux feel free
to change this, I couldn't find the atomic functions anymore though :*( */
void IncRef() { ++ref; }
void DecRef()
{
--ref;
if(ref <= 0)
{
delete cb;
delete this;
}
}
#endif
};
最后事件管理,是个单件模板,
typedef map<int32, EventableObjectHolder*> HolderMap;
class SERVER_DECL EventMgr : public Singleton < EventMgr >
{
friend class MiniEventMgr;
public:
template <class Class>
void AddEvent(Class *obj, void (Class::*method)(), uint32 type, uint32 time, uint32 repeats, uint32 flags)
{
// create a timed event
TimedEvent * event = new TimedEvent(obj, new CallbackP0<Class>(obj, method), type, time, repeats, flags);
// add this to the object's list, updating will all be done later on...
obj->event_AddEvent(event);
}
template <class Class, typename P1>
void AddEvent(Class *obj, void (Class::*method)(P1), P1 p1, uint32 type, uint32 time, uint32 repeats, uint32 flags)
{
// create a timed event
TimedEvent * event = new TimedEvent(obj, new CallbackP1<Class, P1>(obj, method, p1), type, time, repeats, flags);
// add this to the object's list, updating will all be done later on...
obj->event_AddEvent(event);
}
template <class Class, typename P1, typename P2>
void AddEvent(Class *obj, void (Class::*method)(P1,P2), P1 p1, P2 p2, uint32 type, uint32 time, uint32 repeats, uint32 flags)
{
// create a timed event
TimedEvent * event = new TimedEvent(obj, new CallbackP2<Class, P1, P2>(obj, method, p1, p2), type, time, repeats, flags);
// add this to the object's list, updating will all be done later on...
obj->event_AddEvent(event);
}
template <class Class, typename P1, typename P2, typename P3>
void AddEvent(Class *obj,void (Class::*method)(P1,P2,P3), P1 p1, P2 p2, P3 p3, uint32 type, uint32 time, uint32 repeats, uint32 flags)
{
// create a timed event
TimedEvent * event = new TimedEvent(obj, new CallbackP3<Class, P1, P2, P3>(obj, method, p1, p2, p3), type, time, repeats, flags);
// add this to the object's list, updating will all be done later on...
obj->event_AddEvent(event);
}
template <class Class, typename P1, typename P2, typename P3, typename P4>
void AddEvent(Class *obj, void (Class::*method)(P1,P2,P3,P4), P1 p1, P2 p2, P3 p3, P4 p4, uint32 type, uint32 time, uint32 repeats, uint32 flags)
{
// create a timed event
TimedEvent * event = new TimedEvent(obj, new CallbackP4<Class, P1, P2, P3, P4>(obj, method, p1, p2, p3, p4), type, time, repeats, flags);
// add this to the object's list, updating will all be done later on...
obj->event_AddEvent(event);
}
template <class Class> void RemoveEvents(Class *obj) { obj->event_RemoveEvents(-1); }
template <class Class> void RemoveEvents(Class *obj, int32 type)
{
obj->event_RemoveEvents(type);
}
template <class Class> void ModifyEventTimeLeft(Class *obj, uint32 type, uint32 time,bool unconditioned=true)
{
obj->event_ModifyTimeLeft(type, time,unconditioned);
}
template <class Class> void ModifyEventTimeAndTimeLeft(Class *obj, uint32 type, uint32 time)
{
obj->event_ModifyTimeAndTimeLeft(type, time);
}
template <class Class> void ModifyEventTime(Class *obj, uint32 type, uint32 time)
{
obj->event_ModifyTime(type, time);
}
template <class Class> bool HasEvent(Class *obj, uint32 type)
{
return obj->event_HasEvent(type);
}
EventableObjectHolder * GetEventHolder(int32 InstanceId)
{
HolderMap::iterator itr = mHolders.find(InstanceId);
if(itr == mHolders.end()) return 0;
return itr->second;
}
void AddEventHolder(EventableObjectHolder * holder, int32 InstanceId)
{
holderLock.Acquire();
mHolders.insert( HolderMap::value_type( InstanceId, holder) );
holderLock.Release();
}
void RemoveEventHolder(int32 InstanceId)
{
holderLock.Acquire();
mHolders.erase(InstanceId);
holderLock.Release();
}
void RemoveEventHolder(EventableObjectHolder * holder)
{
holderLock.Acquire();
HolderMap::iterator itr = mHolders.begin();
for(; itr != mHolders.end(); ++itr)
{
if(itr->second == holder)
{
mHolders.erase(itr);
holderLock.Release();
return;
}
}
holderLock.Release();
}
protected:
HolderMap mHolders;
Mutex holderLock;
};
#define sEventMgr EventMgr::getSingleton()
这里类把事件操作封装起来,把事件对象,事件参数 处理函数 事件钩子,事件场景所有的都联系起来。 |
|