open source
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
@file JCEmitter.cpp
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
#include "../event/JCEmitter.h"
|
||||
#include "../misc/JCWorkerThread.h"
|
||||
|
||||
namespace laya
|
||||
{
|
||||
JCEventEmitter::JCEventEmitter(){
|
||||
//继承类要在构造中分配 m_AllListener
|
||||
//例如 m_AllListener.resize(MyCls::evtNum);
|
||||
}
|
||||
|
||||
//为了发给线程,需要这样一个函数。TODO 能不用这个转换么
|
||||
void JCEventEmitter::rewrapEventFunc(EventHandler& p_Func, evtPtr p_pEvt){
|
||||
p_Func(p_pEvt);
|
||||
}
|
||||
|
||||
void JCEventEmitter::cleanDelListener(){
|
||||
m_ListenerLock.lock();
|
||||
int nSize = m_AllListener.size();
|
||||
//TODO 还没做呢
|
||||
m_ListenerLock.unlock();
|
||||
}
|
||||
|
||||
//TODO 如果发送到进程,没有处理只缓存一个事件的情况
|
||||
bool JCEventEmitter::emit(evtPtr p_evt ){
|
||||
int nID = p_evt->m_nID;
|
||||
m_ListenerLock.lock();
|
||||
int nNum = (int)m_AllListener.size();
|
||||
m_ListenerLock.unlock();
|
||||
if( nID>nNum )
|
||||
throw -1;
|
||||
|
||||
m_ListenerLock.lock();
|
||||
int& delNum = m_AllListener[nID].nDelNum;
|
||||
delNum = 0;
|
||||
std::vector<int>& allID = m_AllListener[nID].allListener;
|
||||
int curListenerNum = (int)allID.size();
|
||||
if( curListenerNum<=0){
|
||||
m_ListenerLock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<EvtHandlerPack>& curStableListeners = m_AllListener[nID].stableListener;
|
||||
int nStableNum = curStableListeners.size();
|
||||
//拷贝内容,以避免长时间阻塞
|
||||
std::vector<int> idxVector;
|
||||
idxVector.resize(nStableNum);
|
||||
for( int i=0; i<nStableNum; i++)
|
||||
idxVector[i]=i;
|
||||
swap(allID,idxVector); //交换一下,新的idx vector只包含多次监听者的索引。
|
||||
|
||||
std::vector<EvtHandlerPack> workStableListeners;
|
||||
workStableListeners.resize(nStableNum);
|
||||
for(int i=0; i<nStableNum; i++ )
|
||||
workStableListeners[i]=curStableListeners[i]; //这样可能比memcpy更可靠。能执行构造函数。
|
||||
//memcpy(&workStableListeners[0],&m_AllListener[nID].stableListener[0],nStableNum*sizeof(EvtHandlerPack));
|
||||
|
||||
std::vector<EvtHandlerPack> workOnceListener;
|
||||
swap(workOnceListener,m_AllListener[nID].onceListener);
|
||||
m_ListenerLock.unlock();
|
||||
|
||||
for( int i=0; i<curListenerNum; i++ ){
|
||||
int idx = allID[i];
|
||||
bool bOnce = (idx&ONCEMASK)!=0;
|
||||
idx &= IDXMASK;
|
||||
EvtHandlerPack& curHandler = bOnce?workOnceListener[idx]:workStableListeners[idx];
|
||||
if(curHandler.bDel){
|
||||
if(!bOnce)
|
||||
delNum ++;
|
||||
continue;
|
||||
}
|
||||
if( curHandler.pThread ){//如果需要发送到另外的线程执行
|
||||
curHandler.pThread->post( std::bind(&JCEventEmitter::rewrapEventFunc,this, curHandler.func, p_evt));
|
||||
}else{
|
||||
curHandler.func(p_evt);
|
||||
}
|
||||
//workOnceListener.clear(); 不需要,本来就是临时的
|
||||
}
|
||||
|
||||
if( delNum>20 )
|
||||
cleanDelListener();
|
||||
|
||||
return curListenerNum>0;
|
||||
}
|
||||
|
||||
bool JCEventEmitter::emit(int p_nEvent, int p_nP1, int p_nP2 ){
|
||||
throw -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JCEventEmitter::on(int p_nEvent, EventHandler func, JCWorkerThread* p_pInThread){
|
||||
return addEventListener(p_nEvent, func, false, p_pInThread );
|
||||
}
|
||||
|
||||
bool JCEventEmitter::once(int p_nEvent, EventHandler func, JCWorkerThread* p_pInThread ){
|
||||
return addEventListener( p_nEvent, func, true, p_pInThread );
|
||||
}
|
||||
|
||||
bool JCEventEmitter::addEventListener( int p_nEvent, EventHandler p_Func, bool p_bOnce, JCWorkerThread* p_pInThread, int p_nPos ){
|
||||
m_ListenerLock.lock();
|
||||
int nSize = m_AllListener.size();
|
||||
m_ListenerLock.unlock();
|
||||
if( p_nEvent>nSize){
|
||||
printf("监听错误的对象\n");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
EvtHandlerPack evtPack;
|
||||
evtPack.pThread = p_pInThread;
|
||||
evtPack.func = p_Func;
|
||||
evtPack.bDel = false;
|
||||
//TODO p_nPos 还没有用
|
||||
|
||||
m_ListenerLock.lock();
|
||||
if( p_bOnce ){
|
||||
int nPos = m_AllListener[p_nEvent].onceListener.size();
|
||||
m_AllListener[p_nEvent].allListener.push_back(nPos|ONCEMASK);
|
||||
m_AllListener[p_nEvent].onceListener.push_back(evtPack);
|
||||
}else{
|
||||
int nPos = m_AllListener[p_nEvent].stableListener.size();
|
||||
m_AllListener[p_nEvent].allListener.push_back(nPos);
|
||||
m_AllListener[p_nEvent].stableListener.push_back(evtPack);
|
||||
}
|
||||
m_ListenerLock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JCEventEmitter::removeEventListener( int p_nEvent, int id){// EventHandler p_Func ){
|
||||
m_ListenerLock.lock();
|
||||
int nSize = m_AllListener.size();
|
||||
m_ListenerLock.unlock();
|
||||
|
||||
if( p_nEvent>=nSize)
|
||||
return false;
|
||||
|
||||
m_ListenerLock.lock();
|
||||
std::vector<EvtHandlerPack>& curStableListener = m_AllListener[p_nEvent].stableListener;
|
||||
std::vector<EvtHandlerPack>& curOnceListener = m_AllListener[p_nEvent].onceListener;
|
||||
int& delNum = m_AllListener[p_nEvent].nDelNum;
|
||||
//
|
||||
for(int i=0,sz=curStableListener.size(); i<sz; i++){
|
||||
EvtHandlerPack& curHandler = curStableListener[i];
|
||||
if( id == curHandler.nID ){
|
||||
curHandler.bDel = true;
|
||||
delNum++;
|
||||
}
|
||||
}
|
||||
for(int i=0,sz=curOnceListener.size(); i<sz; i++){
|
||||
EvtHandlerPack& curHandler = curOnceListener[i];
|
||||
if( id == curHandler.nID ){
|
||||
curHandler.bDel = true;
|
||||
delNum++;
|
||||
}
|
||||
}
|
||||
|
||||
m_ListenerLock.unlock();
|
||||
|
||||
//清理
|
||||
if(delNum>20)
|
||||
cleanDelListener();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void JCEventEmitter::removeEventListener(int p_nEvent ){
|
||||
m_ListenerLock.lock();
|
||||
int nSize = m_AllListener.size();
|
||||
m_ListenerLock.unlock();
|
||||
|
||||
if( p_nEvent>=nSize)
|
||||
return ;
|
||||
m_ListenerLock.lock();
|
||||
m_AllListener[p_nEvent].allListener.clear();
|
||||
m_AllListener[p_nEvent].stableListener.clear();
|
||||
m_AllListener[p_nEvent].onceListener.clear();
|
||||
m_ListenerLock.unlock();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
@file JCEmitter.h
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
#ifndef __JCEmitter_H__
|
||||
#define __JCEmitter_H__
|
||||
|
||||
#include "JCEventBase.h"
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace laya
|
||||
{
|
||||
class JCWorkerThread;
|
||||
/**
|
||||
* @brief 事件发生器。 事件id是并不是全局事件的唯一id,这个id是可以重复的,只有针对具体的emitter才有意义。
|
||||
*/
|
||||
class JCEventEmitter
|
||||
{
|
||||
public:
|
||||
enum evtexample {
|
||||
evtNumExample = 0
|
||||
};
|
||||
//因为事件不能传指针(会发生有人发送临时事件对象的情况),所以统一成智能指针
|
||||
typedef std::shared_ptr<JCEventBase> evtPtr;
|
||||
typedef std::function<void(evtPtr)> EventHandler;
|
||||
struct EvtHandlerPack {
|
||||
EventHandler func;
|
||||
JCWorkerThread* pThread;
|
||||
int nID : 31;
|
||||
bool bDel : 1; //是否删除了
|
||||
};
|
||||
|
||||
protected:
|
||||
struct EventData {
|
||||
std::vector<int> allListener; //这个是为了保证正确的执行顺序。
|
||||
std::vector<EvtHandlerPack> stableListener; //不删除就一直存在的。
|
||||
std::vector<EvtHandlerPack> onceListener; //一次性的。每次用完都会清理
|
||||
//std::vector<int> runData;//事件的运行时数据。例如是否还缓存在线程队列中。这样可以处理只缓存一个的情况
|
||||
int nDelNum; //监听对象被删除的个数,当超过一定的时候需要清理
|
||||
EventData() {
|
||||
nDelNum = 0;
|
||||
}
|
||||
};
|
||||
typedef std::vector< EventData > EventListener;
|
||||
|
||||
public:
|
||||
JCEventEmitter();
|
||||
|
||||
//例如根据this和函数指针来生成id,这样调用者就不用保存id了
|
||||
static int makeID(int, int);
|
||||
bool emit(evtPtr p_evt );
|
||||
bool emit(int p_nEvent, int p_nP1, int p_nP2 );
|
||||
|
||||
//p_pInThread 表示在哪个线程中执行。如果不设置,则是立即回调的方式
|
||||
//id 用来唯一标识一个回调。
|
||||
bool on(int p_nEvent, EventHandler func, /*int id,*/ JCWorkerThread* p_pInThread=0); //p_nEvent
|
||||
|
||||
bool once(int p_nEvent, EventHandler func, JCWorkerThread* p_pInThread=0 );
|
||||
|
||||
bool addEventListener( int p_nEvent, EventHandler p_Func, bool p_bOnce, JCWorkerThread* p_pInThread=0, int p_nPos=-1 );
|
||||
|
||||
bool removeEventListener(int p_nEvent, int id );
|
||||
|
||||
//删掉某个事件的所有监听者。
|
||||
void removeEventListener(int p_nEvent );
|
||||
|
||||
protected:
|
||||
//把事件处理函数包装成线程处理函数
|
||||
void rewrapEventFunc(EventHandler& p_Func, evtPtr p_pEvt);
|
||||
void cleanDelListener(); //清理队列,去掉已经被删除的。
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
public:
|
||||
static const int ONCEMASK = 0x8000; //这个位为1则表示是一次性的。
|
||||
static const int IDXMASK = 0x7fff; //取出位置的
|
||||
EventListener m_AllListener;
|
||||
std::recursive_mutex m_ListenerLock; //同线程的不要阻塞
|
||||
};
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JCEmitter_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
@file JCEventBase.cpp
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
//包含头文件
|
||||
#include "../event/JCEventBase.h"
|
||||
//------------------------------------------------------------------------------
|
||||
namespace laya
|
||||
{
|
||||
JCEventBase::JCEventBase()
|
||||
{
|
||||
m_nID=0;
|
||||
m_pName=0;
|
||||
m_nFlags=0;
|
||||
m_nPriority=0; //优先级
|
||||
m_nP1=m_nP2=0;
|
||||
m_pData=0; //外面分配,需要自己释放。
|
||||
}
|
||||
JCEventBase::~JCEventBase()
|
||||
{
|
||||
/*
|
||||
if( m_pData && (m_nFlags&NEEDDELDATA)){
|
||||
delete m_pData;
|
||||
m_pData = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
@file JCEventBase.h
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
#ifndef __JCEventBase_H__
|
||||
#define __JCEventBase_H__
|
||||
|
||||
namespace laya
|
||||
{
|
||||
class JCEventBase
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
HANDLE_ONCE=0x1,//只处理一次,不会派发给队列中的其他监听者。好像没有为n的需求。
|
||||
ISCALLBACK=0x2, //立即回调。不压队列
|
||||
UNIQUE=0x4, //排他性,在队列中只有一个。
|
||||
NEEDDELDATA=0x5, //m_pData需要释放
|
||||
};
|
||||
|
||||
public:
|
||||
JCEventBase();
|
||||
~JCEventBase();
|
||||
void setDataAsPtr(void* pData) { m_pData = pData; m_nFlags |= NEEDDELDATA; };
|
||||
void setDataAsInt(int data){ m_pData = (void*)data; m_nFlags&=(~NEEDDELDATA);}
|
||||
void* getData(){return m_pData; }
|
||||
public:
|
||||
int m_nID;
|
||||
char* m_pName;
|
||||
unsigned int m_nFlags;
|
||||
char m_nPriority; //优先级
|
||||
int m_nP1, m_nP2;
|
||||
protected:
|
||||
void* m_pData; //外面分配,需要自己释放。
|
||||
|
||||
};
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JCEventBase_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
Reference in New Issue
Block a user