您的位置:首页 > 编程语言 > C语言/C++

libevent C++面向对象的封装

2013-09-15 10:42 302 查看

libevent C++面向对象的封装

作者:方振涛
对event_base操作的封装如下:

class TEventContext
{
public:
static void InitLib()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData);
}

public:
TEventContext(event_base* evbase=NULL):m_evBase(evbase){}
~TEventContext(){
if (m_evBase)
{
event_base_free(m_evBase);
}
}
bool Init()
{
if(m_evBase)
return false;
m_evBase=event_base_new();
return m_evBase!=NULL;
}
bool ReInit()
{
return event_reinit(m_evBase)==0;
}
bool Dispatch()//进入事件处理循环
{
return event_base_dispatch(m_evBase)==0;
}
const char*GetMethod()
{
return event_base_get_method(m_evBase);
}
int GetFeatures(){return event_base_get_features(m_evBase);}

enum
{
FLoopOnce=EVLOOP_ONCE,
FLoopNonBlock=EVLOOP_NONBLOCK,
};
//进入事件循环
bool Loop(int flags)
{
return event_base_loop(m_evBase,flags)==0;
}

//退出循环
bool ExitLoop( const struct timeval *timev)
{
return event_base_loopexit(m_evBase,timev)==0;
}
bool BreakLoop()
{
return event_base_loopbreak(m_evBase)==0;

}

bool GotExit()
{
return event_base_got_exit(m_evBase)!=0;
}

bool GotBreak()
{
return event_base_got_break(m_evBase)!=0;
}

event_base* GetEvBase()
{
return m_evBase;
}

private:
event_base* m_evBase;
};

封装对event的操作:

class TEvent
{
public:
TEvent()
{
memset(&m_event,0,sizeof(m_event));
}

template<class EventHandler>
bool Assign(TEventContext* ctx,EventHandler* handler)
{
return event_assign(&m_event,ctx->GetEvBase(),handler->GetFd(),handler->GetType(),EventHandler::HandlerFunc,handler)==0;
}

bool Add(const struct timeval *tmv)
{
return event_add(&m_event,tmv)==0;
}

bool Remove()
{
return event_del(&m_event)==0;
}

void Active(int res, short ncalls)
{
event_active(&m_event,res,ncalls);
}

bool CheckPending(short events, struct timeval *tv)
{
return event_pending(&m_event,events,tv)!=0;
}

bool IsInitialized()
{
return event_initialized(&m_event)!=0;
}

evutil_socket_t GetFd()
{
return event_get_fd(&m_event);
}

short GetEvent()
{
return event_get_events(&m_event);
}
private:
TEvent(TEvent&){}
TEvent& operator=(TEvent&){}
struct event m_event;//仅保存数据
};

下面来说说关于如何处理到来的事件:

一般很容易会想到事件到来后通过虚函数来实现对事件的处理,但对于服务器来说尽量做到高效率,使用虚函数会造成不必要的性能损失。

受到WTL库使用模板来替代虚函数,来完成对事件的处理。

事件的处理实现如下:

template<class Handler>
class TEventHandler
{
public:
enum EventFlag
{
FTimeOut=EV_TIMEOUT,
FRead=EV_READ,
FWrite=EV_WRITE,
FSignal=EV_SIGNAL,
FPersist=EV_PERSIST,
FEt=EV_ET,
};

public:
TEventHandler(evutil_socket_t fd,short type):m_fd(fd),m_type(type){}

static void HandlerFunc(evutil_socket_t fd, short eventType, void *arg)
{
TEventHandler* handler=(TEventHandler*)arg;

handler->m_fd=fd;
handler->m_type=eventType;
handler->OnEventHandle();
}

inline void OnEventHandle()//不能使用OnHandle,防止子类未重写导致死循环
{
Handler* chandler= static_cast<Handler*>(this);
chandler->OnHandle();
}

evutil_socket_t GetFd(){return m_fd;}
short GetType(){return m_type;}
protected:
evutil_socket_t m_fd;
short m_type;
};


在OnEventHandle函数中通过转换来实现调用相应子类实现的处理函数

template<class Handler>
class TTimerHandler:public TEventHandler<Handler>
{
public:
TTimerHandler():TEventHandler(-1,0){}
};

template<class Handler>
class TSingalHandler:public TEventHandler<Handler>
{
public:
TSingalHandler(evutil_socket_t fd):TEventHandler(fd,EV_SIGNAL|EV_PERSIST){}
};


测试代码如下:

struct timeval lasttime;

int event_is_persistent;

class MyHandler:public TTimerHandler<MyHandler>
{
public:
TEvent* m_event;
MyHandler(TEvent *ev):m_event(ev)
{}

void OnHandle()
{
struct timeval newtime, difference;
double elapsed;

evutil_gettimeofday(&newtime, NULL);
evutil_timersub(&newtime, &lasttime, &difference);
elapsed = difference.tv_sec +
(difference.tv_usec / 1.0e6);

printf("timeout_cb called at %d: %.3f seconds elapsed.\n",
(int)newtime.tv_sec, elapsed);
lasttime = newtime;

if (! event_is_persistent) {
struct timeval tv;
evutil_timerclear(&tv);
tv.tv_sec = 2;
m_event->Add(&tv);
}

}

};

int _tmain(int argc, char* argv[])
{

if (argc == 2 && !strcmp(argv[1], "-p")) {
event_is_persistent = 1;
} else {
event_is_persistent = 0;
}

TEventContext::InitLib();

TEventContext base;

base.Init();

TEvent ev;

MyHandler handler(&ev);
ev.Assign(&base,&handler);

struct timeval tv;
evutil_timerclear(&tv);
tv.tv_sec = 2;
ev.Add(&tv);

evutil_gettimeofday(&lasttime, NULL);

base.Dispatch();
return 0;
}


此文档属本人原创,欢迎转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: