libevent C++面向对象的封装

时间:2022-05-14 00:18:17

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;
}

此文档属本人原创,欢迎转载。