上一篇我们封装了三种事件监听方式,如果分别提供给客户端使用,有点不方便,也不利于统一管理;我们再封装一层EventLoop。

/***************************************************************************************
****************************************************************************************
* FILE		: event_loop.h
* Description	: 
*			  
* Copyright (c) 2012 by Liu Yanyun(E-mail:liuyun827@foxmail.com). All Rights Reserved.
*            Without permission, shall not be used for any commercial purpose
* 
* History:
* Version		Name       		Date			Description
   0.1		Liu Yanyun		2012/12/20		Initial Version
   
****************************************************************************************
****************************************************************************************/


#ifndef _EVENT_LOOP_H_
#define _EVENT_LOOP_H_

#include <string.h>
#include <stdint.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <poll.h>
#include "sock_ev.h"

class Socket;
class EventDispatcher;


/*==================================================================
* Function	: EventLoop
* Description	: event loop,it is adapter for select poll epoll wait event
==================================================================*/
class EventLoop
{
public:

  /*==================================================================
  * Function	: EventLoop.EventLoop
  * Description	: construction function
  ==================================================================*/
  EventLoop();

  /*==================================================================
  * Function	: EventLoop.~EventLoop
  * Description	: Destructor function
  ==================================================================*/
  virtual ~EventLoop();

  /*==================================================================
  * Function	: EventLoop.initialize
  * Description	: initialize the loop
  * Input Para	: type_--dispatcher type
  * Return Value: success return true,or else return false
  ==================================================================*/
  bool initialize(LoopType type_);

  /*==================================================================
  * Function	: EventLoop.addEvt
  * Description	: add an event and register callback
  * Input Para	: 
  * Output Para	: 
  * Return Value: success return true,or else return false
  ==================================================================*/
  bool addEvt(Socket *sock_,
      EvCallBack cb_,
      EventType evt_,
      void *arg_);

  /*==================================================================
  * Function	: EventLoop.removeEvt
  * Description	: remove an event and un-register callback
  * Input Para	: 
  * Output Para	: 
  * Return Value: success return true,or else return false
  ==================================================================*/
  bool removeEvt(Socket *sock_,
      EventType evt_);

  /*==================================================================
  * Function	: EventLoop.listen
  * Description	: wait for event trigger
  * Input Para	: 
  * Output Para	: 
  * Return Value: 
  ==================================================================*/
  int listen(int timeout_);
      
private:

    EventDispatcher *dispatcher;
    SockMapT  sockMap;
};

#endif /*_EVENT_LOOP_H_*/


 

#include "event_loop.h"
#include "sock_ev.h"
#include "event_dispatcher.h"
#include "socket_base.h"
#include "socket.h"


EventLoop::EventLoop()
{
  dispatcher = NULL;
}
EventLoop::~EventLoop()
{
  if(NULL != dispatcher) delete dispatcher;

  sockMap.clear();
}
bool EventLoop::initialize(LoopType type_)
{
  if(selectLoop == type_)
  {
    dispatcher = new SelectDispatcher();
  }
  else if(pollLoop == type_)
  {
    dispatcher = new PollDispatcher();
  }
  else if(epollLoop == type_)
  {
    dispatcher = new EpollDispatcher();
  }
  else
  {
    logTrace("loop type is not right:%d", type_);
    return false;
  }

  if(NULL == dispatcher)
  {
    logTrace("new EventDispatcher is failed");
    return false;
  }

  if(!dispatcher->initialize())
  {
    logTrace("dispatcher->initialize() is failed");
    return false;
  }

  return true;
}
bool EventLoop::addEvt(Socket *sock_,
    EvCallBack cb_,
    EventType evt_,
    void *arg_)
{
  if((NULL == sock_) || (-1 == sock_->getFd()) || (NULL == cb_))
  {
    logTrace("addEvt input is not valid,pleace check");
    return false;
  }

  if(!dispatcher->addEvt(this, sock_, cb_, evt_, arg_))
  {
    logTrace("addEvt event to loop is failed");
    return false;
  }

  sockMap[sock_->getFd()] = sock_;

  return true;
}
bool EventLoop::removeEvt(Socket *sock_,
    EventType evt_)
{
  if((NULL == sock_) || (-1 == sock_->getFd()))
  {
    logTrace("removeEvt input is not valid,pleace check");
    return false;
  }

  dispatcher->removeEvt(sock_, evt_);

  EventType evt = sock_->getEvt();
  if(0 == evt)
  {
    sockMap.erase(sock_->getFd());
  }

  return true;
}
int EventLoop::listen(int timeout_)
{
  while(1)
  {
    dispatcher->listen(sockMap, timeout_);
  }
}

主要调用前一篇中封装的三种事件监听方式,在初始化的时候选择一种event dipatcher,这就是面向接口编程的好处,利用多态,可以很方便的在运行时进行行为的改变。成员变量sockMap用于保存注册到EventLoop中的socket。

Logo

更多推荐