前文已经提过,要模仿VNPY的设计来做,那么其中最重要的莫过于他的核心,也就是基于事件的消息传递。我从CppVnpy项目中找到事件的定义:
#define EVENT_LOG "eLog" //# 日志事件,通常使用某个监听函数直接显示
#define EVENT_TDLOGIN "eTdLogin" //# 交易服务器登录成功事件
#define EVENT_TIMER "eTimer" //# 计时器事件,每隔1秒发送一次
#define EVENT_CONTRACT "eContract" // # 合约查询回报事件
#define EVENT_INVESTOR "eInvestor" // # 投资者查询回报事件
#define EVENT_ACCOUNT "eAccount" // # 账户查询回报事件
#define EVENT_POSITION "ePosition" // # 持仓查询回报事件
#define EVENT_POSITION_UI "ePositionUI" // # 持仓查询回报事件(更新UI)
#define EVENT_TICK "eTick" //# 行情推送事件
#define EVENT_TICK_CONTRACT "eTick." //# 特定合约的行情事件
#define EVENT_ORDER "eOrder" //# 报单推送事件
#define EVENT_ORDER_ORDERREF "eOrder." //# 特定报单号的报单事件
#define EVENT_TRADE "eTrade" //# 成交推送事件
#define EVENT_TRADE_CONTRACT "eTrade." //# 特定合约的成交事件
//
#define EVENT_STG_BEG "eBegStg" //# CTA策略开启事件
#define EVENT_STG_END "eEngStg" //# CTA策略关闭事件
而后,事件的定义如下:
// 将Event传到每一个回调函数中,data_包含堆上的数据指针,仿vnpy,在回调函数内部将char* data转换为需要的数据类型
// 后期可以使用tc_malloc将所有的new截取到内存池中,提升性能的同时避免内存碎片
struct Event
{
Event() = default;
Event(std::string type) : type_(type){}
std::string type_;
std::shared_ptr<char> data_;
};
首先,关于事件的定义,其实都是宏定义,而项目中都使用字符串,或许把它改为整型数会更好。
另外,事件的定义中,有事件的类型,事件所带的数据。那么,在EventEngine中,addEvent方法也就是把事件(含数据)插入到一个list容器中,然后通过process方法来对list中每个事件进行处理。
回到自己的设计中,首先还是应当了解一下如果是自己的程序中,会有哪些事件需要处理,而谁是处理事件的对象。
大概是这样子描述:
原本为了学习事件驱动编程,也找过其他的写的系统,也有看了一下关于使用libevent库的教程,但可能技术含量都比较高,而不适合自己,后来一想,其实MFC的程序本身就已经有消息循环的机制,为什么还要自己造轮子呢?
于是尝试直接使用窗口对象的消息循环来。
大概的设计方案如下: