Nox学习(4)——构建一个自己的Nox-2

      我倾向于把事情简单化,Nox的运行基本上涵盖了如下几个过程:

      1、openflow协议报文交互

      2、处理逻辑以及事件生成

      3、事件分发及应用回调处理

      4、应用管理与部署

      把Nox说得更简单点就是:生产事件-->消费事件。至于如何生产,如何消费则是进一步需要细化了解的地方。

     

      运行过程的总结中“事件分发”衔接了协议报文交互与应用逻辑,是Nox的核心之一,这次先打通“事件分发”这一脉。

      下图是实现一个简单的事件分发组件的模型:

      事件分发在整个应用中只需要一个对象来完成,因此,Nox实现了一个单态的event dispatcher,其内部主要维护了如上模型图中的三样东西。event dispather是事件的消费者,所有的事件都交给他来处理。

      打个比方吧,event dispatcher就如同银行,总部制定了银行可以从事的各项业务(Application),并规定了各业务该如何办理,要填哪些表格,要做哪些记录,分发出去卡、还是凭证、还是一个U盾等等吧,银行的业务人员(线程)只需要按照这个规程进行办事就可以了。当然,银行最先需要的就是开个店面(init),还要有熟悉规程的业务人员(工作线程),这样,我们才可以去银行办理各种业务(事件,当然,这里的比喻还是有差别的,event dispatcher的事件可以激活一系列的业务的处理函数),办理业务的人多了,就需要排队(post到任务队列),直到叫到你的号的时候,才能真正开始办理(回调处理);如果你是个VIP,恭喜你,你立马就能办理业务了(dispatch调用)。

     

      1、组件定义: 下面是Event_dispatcher类的一个实现示例

// event_dispatcher.hh

class Event_dispatcher
{
public:
    static Event_dispatcher *get_instance();
    static void init();
    void start();
    void shutdown();
    void register_handler(const Event_name& event_name,
                          const Event_handler& handler, 
                          int order);
    void post(const Event& event);
    void dispatch(const Event& event) const;

    boost::asio::io_service& get_io_service();
    
private:   
    typedef std::multiset<Event_handler_wrapper> Call_chain;
    typedef boost::unordered_map<Event_name, Call_chain> Call_chain_map;
    
    static Event_dispatcher *event_dispatcher;
    Event_dispatcher();

    void _create_work_thread();

    /* the io_service object and work */
    boost::asio::io_service io;
    boost::asio::io_service::work work;

    /* number of threads to spawn */
    size_t n_threads; // 暂未使用
    boost::thread_group tg;

    Call_chain_map call_chain_map;    
};

 

// event_dispatcher.cc

Event_dispatcher *Event_dispatcher::event_dispatcher = NULL;

void Event_dispatcher::init()
{
    printf("### Event_dispatcher: init ... \n");
    if (!event_dispatcher)
    {
        event_dispatcher = new Event_dispatcher();
    }
}

void Event_dispatcher::start()
{
    tg.join_all();
}

void Event_dispatcher::shutdown()
{
    io.stop();
}

void Event_dispatcher::register_handler(const Event_name& event_name,
                                        const Event_handler& handler, 
                                        int order)
{
    printf("### Event_dispatcher: Registering event '%s' handler by order %d.\n", 
           event_name.c_str(), order);

    Event_handler_wrapper ehw(handler, order);
    call_chain_map[event_name].insert(ehw);
}

void Event_dispatcher::post(const Event& event)
{
    printf("### Event_dispatcher: post event ... \n");
    io.post(boost::bind(&Event_dispatcher::dispatch, this, boost::cref(event)));
}

void Event_dispatcher::dispatch(const Event& event) const
{
    printf("### Event_dispatcher: dispatch ... \n");

    const Event_name& event_name = event.get_name();
    Call_chain_map::const_iterator it = call_chain_map.find(event_name);
    if (it != call_chain_map.end())
    {
        const Call_chain& call_chain = it->second;
        BOOST_FOREACH(const Event_handler_wrapper& ehw, call_chain)
        {
            try
            {
                printf("### Event_dispatcher: dispatch event %s ........ \n", event.get_name().c_str());
                if (ehw(event) == STOP)
                {
                    break;
                }
            }
            catch (const std::exception& e)
            {
                break;
            }
        }
    }
}

boost::asio::io_service& Event_dispatcher::get_io_service()
{
    return io;
}

Event_dispatcher *Event_dispatcher::get_instance()
{
    return Event_dispatcher::event_dispatcher;
}

void Event_dispatcher::_create_work_thread()
{
    printf("### Event_dispatcher: creating thread ... \n");
    tg.create_thread(boost::bind(&boost::asio::io_service::run, &io));
}

Event_dispatcher::Event_dispatcher()
    : io(), work(io)
{
    printf("### Event_dispatcher: constructor ... \n");
    _create_work_thread();
}

 

// event_handler_wrapper.cc 辅助类定义

typedef boost::function<Event_handler_signature> Event_handler;

class Event_handler_wrapper
{
public:
    Event_handler_wrapper(const Event_handler& eh, int p)
        : event_handler(eh), priority(p)
    {
    }

    bool operator<(const Event_handler_wrapper& that) const
    {
        return priority < that.priority;
    }

    Disposition operator()(const Event& event) const
    {
        assert(!event_handler.empty());
        return event_handler(event);
    }
private:
    Event_handler event_handler;
    int priority;
};

 

   2、组件使用: 下面开始是完成一个shutdown事件的相关代码

// event.hh

typedef std::string Event_name;

class Event
{
public:
    virtual ~Event() {}
    Event_name get_name() const { return name; }

protected:
    Event(const Event_name& name_) : name(name_) {}
    //void set_name(const Event_name& name_) { name = name_; }

private:
    const Event_name name;
}; 

 

// shutdown_event.hh

class Shutdown_event : public Event
{
public:
    Shutdown_event() : Event(static_get_name()) { }

    static const Event_name static_get_name()
    {
        return "Shutdown_event";
    }
};

void register_shutdown();

 

// shutdown_event.cc

static boost::function<void()> post_shutdown;

static void _signal_to_shutdown(int param)
{
	printf("### shutdown event: post shutdown event on signal %d.\n", param);
	post_shutdown();
}

static Disposition _shutdown_handler(Event_dispatcher *event_dispatcher,
                                     const Event& event)
{
    printf("### handle shutting down event.\n");
    event_dispatcher->shutdown();
    return CONTINUE;
}

static void _register_shutdown_signal()
{
    signal(SIGTERM, _signal_to_shutdown);
    signal(SIGINT, _signal_to_shutdown);
    signal(SIGHUP, _signal_to_shutdown);
    signal(SIGABRT, _signal_to_shutdown);
}

void register_shutdown()
{
    Event_dispatcher *event_dispatcher = Event_dispatcher::get_instance();
    
    event_dispatcher->register_handler(Shutdown_event::static_get_name(), 
                                       boost::bind(&_shutdown_handler, event_dispatcher, _1), 
                                       9999);
    post_shutdown = boost::bind(&Event_dispatcher::post, event_dispatcher, Shutdown_event());
        
    _register_shutdown_signal();
} 

 

      3、展示: 下面是修改main函数中的代码,编译执行

// main.cc修改的部分

int main(int argc, char *argv[])
{
    _show_welcome(argv[0]);
    Event_dispatcher::init();
    register_shutdown();
    Event_dispatcher::get_instance()->start();
    
    return 0;
}       

  

编译执行结果如下:

root@ubuntu:/home/y09002/My-Nox# make all
g++ -g -rdynamic -lboost_system -lboost_thread\
        main.cc event_dispatcher/event_dispatcher.cc event/shutdown_event.cc -o My_Nox
root@ubuntu:/home/y09002/My-Nox# ./My_Nox
################### Welcome to use My_Nox! ###################
### Event_dispatcher: init ...
### Event_dispatcher: constructor ...
### Event_dispatcher: creating thread ...
### Event_dispatcher: Registering event 'Shutdown_event' handler by order 9999.
^C### shutdown event: post shutdown event on signal 2.
### Event_dispatcher: post event ...
### Event_dispatcher: dispatch ...
### Event_dispatcher: dispatch event Shutdown_event ........
### handle shutting down event.

 

按下ctrl+c之后,看到post了shutdown事件,然后dispatch了,最后habdle了。不过shutdown事件演示的跟Nox的实现稍微有所差别,我也没有把Event_dispatcher类归属于Nox实现中所说的Component类,毕竟Event_dispatcher真有必要统一抽象成Component,然后放在kernel中与其他Component一样管理吗,而且有Component_context的必要么?不纳入Component的继承层次也许是更好的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值