加载中…
个人资料
我想故我在
我想故我在
  • 博客等级:
  • 博客积分:0
  • 博客访问:9,890
  • 关注人气:4
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

[连载]基于消息驱动的面向对象通用C/S应用框架(16)

(2009-01-19 13:41:19)
标签:

c/s应用框架

消息驱动

消息映射表

面向对象

cplusplus

c/s

it

分类: 应用框架

2.11 框架重构:消息处理器及其注册方法的改进

        我们有理由假设客户端或服务器端的应用层需要定义很多的业务消息,这些业务消息不仅可以按相关程度分组,而且有些消息来往比较频繁而有的消息则很少发送。按照逻辑上的相关性或者处理上的方便性,消息分组后可为每一组消息定义一个消息处理器(当然,为每一个消息定义一个消息处理器也未尝不可,但是会导致处理器列表很长,消息分发效率会受到影响,所以不建议这样做!)。那么对于消息的接收端来说,频繁发生的消息就可能需要尽快地分发和处理,也就是尽量提高其分发和处理效率。处理函数的效率在框架层是没法控制的,那么如何提高消息分发的效率呢?

        这里提供两个途径,一个方法和一个建议,方法可以在框架层强制实施,但是建议只能由应用层开发人员尽量遵守。这个方法就是:为每个消息处理器规定优先级,就用数字来表示吧,优先级较大的消息处理器将被排在消息处理器列表的前面,相反优先级较小的处理器将排在列表的后面。那么建议就是:在初始化每个消息处理器的消息映射表时,尽量把发送频率较高的消息对应的映射项放在前面。也就是说,对于发送频率较高的消息,为其处理器指定较高的优先级,同时优化消息映射表项的顺序。此外,由于各个消息处理器对象是通过两个宏REGISTER_MESSAGE_PROCESSOR()和IMPLEMENT_MESSAGE_PROCESSOR()自动创建和注册的,甚至自动创建的方式都可以改变,而应用层开发人员并不需要知道它们的存在以及存在的具体形式,但是仍然可能需要显式地调用它们,所以框架层必须提供某种方法使得应用层开发人员在需要时能够得到这些对象,而且最好是它们的指针。这在本章最后2.17节中将有用武之地。

        综合这些需求,首先需要改进接口MessageProcessor的定义:

typedef UINT  ProcessorPriority;

class MessageProcessor

{

    DECLARE_MESSAGE_MAP_TABLE()

public:

    virtual ~MessageProcessor() = 0;

public:

    virtual ProcessorPriority GetPriority() const = 0;

    virtual const char* GetClassName() const = 0;

    static SerialNumber GetNextSn(); // 生成下一个消息序列号

public:

    //  客户端模块发出的请求消息的缓存区,应用层请求消息都应该在发出之前

    //  首先缓存到此处,以便接收端回发的应答消息可以在这里找到与其匹配的

    //  请求消息。具体实现参见头文件HYQ_req_message_buffer.h。

#if !defined(_CENTRAL_SERVER_)

    static MessageBuffer  gs_outRequestMsgBuffer;

#endif 

};

        任何具体消息处理器通过改写虚函数GetPriority()来设置和返回自己的优先级,通过改写GetClassName()返回自己的类名称。

        然后,在各个消息处理器对象注册的时候,或者在全部注册完毕之后、启动消息分发线程之前,按照优先级从高到底对消息处理器列表进行排序。为此,我们重新定义消息处理器列表如下:

typedef STD::map<ProcessorPriority,

                 MessageProcessor*,

                 STD::greater_equal<ProcessorPriority> > \

        MessageProcessorList;

        这样就不需要我们显式调用STD::sort()算法来排序了,因为STD::map<>可以在插入元素时自动排序。

另外,消息处理器注册时机和消息分发线程启动时机之间潜在的顺序问题,终究是一个隐患,所以我们必须设法确保所有消息处理器都在消息分发线程启动之前注册完毕。因此,必须放弃前面的直接注册方法(即直接操纵消息处理器列表),而应该在MessageDispatcher的构造函数调用this->start();之前通过显式地调用一个函数来完成消息处理器列表的构建。由于在MessageProcessor的构造函数中不能直接操作MessageDispatcher的消息处理器列表,因此需要定义一个中间列表:

class MessageProcessorRegistery

{

    typedef STD::list<MessageProcessor*> _TempProcList;

    static _TempProcList gs_TempProcList; // 临时表

public:

    static void Register(MessageProcessor* pproc);

    static void BuildProcessorList(MessageProcessorList& procList);

};

        然后,修改MessageProcessor的构造函数实现如下:

MessageProcessor::MessageProcessor()

{

    MessageProcessorRegistery::Register(this); // 先注册到中间列表中

}

        最后,修改MessageDispatcher的构造函数实现如下:

MessageDispatcher::MessageDispatcher()

{

#ifdef _CENTRAL_SERVER_

    m_theDemultiplexer = MessageDemultiplexerFactory::get_instance();

#else

    MessageProcessorRegistery::BuildProcessorList(m_processorList);

#endif

 

    this->start();  // 自动启动分发线程

}

        同样地,服务器端MessageDemultiplexer的构造函数实现如下:

MessageDemultiplexer::MessageDemultiplexer()

{

    MessageProcessorRegistery::BuildProcessorList(m_processorList);

}

        很容易想象,MessageProcessorRegistery类的实现如下:

_TempProcList MessageProcessorRegistery::gs_TempProcList;

void MessageProcessorRegistery::Register(MessageProcessor* pproc)

{ gs_TempProcList.push_back(pproc); }

void MessageProcessorRegistery::

BuildProcessorList(MessageProcessorList& procList)

{

    assert(!gs_TempProcList.empty());

    procList.clear();

    for (_TempProcList::const_iterator

         first = gs_TempProcList.begin();

         first != gs_TempProcList.end();

         ++first)

        {

        procList[(*first)->GetPriority()] = (*first); // 自动排序

        }

}

        而宏REGISTER_MESSAGE_PROCESSOR()和IMPLEMENT_MESSAGE_PROCESSOR()的定义并不需要修改,所以应用层消息处理器的定义和实现也都不需要修改。

        这样做的另一个好处是,每当应用层需要MessageDispatcher对象或MessageDemultiplexer对象的时候,总是能够保证真正的消息处理器列表已经构建完毕。

        在所有消息处理器自动注册完毕后,为了能够在需要时找回每个对象,需要在类MessageDispatcher和MessageDemultiplexer中增加以类名为输入参数的查找函数FindProcessor():

class MessageDispatcher : public Thread, public MessageReceiver

{

    DECLARE_STATIC_SINGLETON(MessageDispatcher)

public:

    virtual void stop();  // 重写Thread::stop()

#if !defined(_CENTRAL_SERVER_)

    MessageProcessor* FindProcessor(const STD::string& className) const;

#endif

private:

    …… // 其他定义都相同

};

        其实现如下:

#if !defined(_CENTRAL_SERVER_)

MessageProcessor* \

MessageDispatcher::FindProcessor(const STD::string& className) const

{

    for (MessageProcessorList::const_iterator

        first = m_processorList.begin();

        first != m_processorList.end();

        ++first)

        {

        if (className == first->second->GetClassName())

            return (first->second);

        }

    return NULL;

}

#endif

        MessageDemultiplexer::FindProcessor()的实现完全相同。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有