业务痛点
历史包袱——使用原生mars组件进行小包的收发,弱网场景下单实例的mars不能支撑高频&多样的业务模型,所以迫切需要一个支持多实例的网络组件来处理业务收发,libevent是一个方案。由于libevent本身并没有封装任务调度器,需要自行设计开发。
设计思路
设计一个异步事件发生器,借助libevent支持延迟触发,借助socket实现进程间通信,这样能很好地支持业务中所有需要同步接口改异步的需求。 很简单,内部开个线程处理回调队列,增加延迟触发逻辑。
代码实现
namespace MsgComm {
class ClientEventLoopConcrete : public ClientEventLoop {
public:
ClientEventLoopConcrete();
~ClientEventLoopConcrete() override;
struct event_base* EventBase() override {
return m_eventBase;
}
int AsyncCall(std::weak_ptr<ClientEventLoopCallback> callBack, const uint64_t& delay) override;
private:
friend std::shared_ptr<ClientEventLoop> GetEventLoop(const ClientEventLoopType& type);
friend void OnClientEventLoopConcreteEventCallback(evutil_socket_t sockFd, short event, void *userCtx);
int start();
int stop();
void threadFunc();
void onEventCallback(evutil_socket_t sockFd, short event);
int createSocketPair();
void destroySocketPair();
void onAlarm();
struct event_base* m_eventBase;
struct event* m_event;
std::atomic_bool m_exitFlag;
std::thread m_thread;
std::mutex m_mutex;
std::condition_variable m_condition;
std::map<int64_t, std::list<std::weak_ptr<ClientEventLoopCallback>>> m_callBacks;
evutil_socket_t m_socketPair[2];
std::shared_ptr<Alarm> m_alarm;
#ifdef ANDROID
std::shared_ptr<WakeUpLock> m_wakeupLock;
#endif
};
};
namespace MsgComm {
#define DEFAULT_SLEEP_TIME_SEC (10)
#define DEFAULT_SLEEP_TIME_USEC (0)
void OnClientEventLoopConcreteEventCallback(evutil_socket_t sockFd, short event, void *userCtx) {
if (userCtx != nullptr) {
reinterpret_cast<ClientEventLoopConcrete*>(userCtx)->onEventCallback(sockFd, event);
}
}
ClientEventLoopConcrete::ClientEventLoopConcrete() : m_eventBase(nullptr),
m_event(nullptr),
m_exitFlag(true),
m_socketPair{-1} {
#ifdef ANDROID
m_wakeupLock = std::make_shared<WakeUpLock>();
#endif
m_alarm = std::make_shared<Alarm>([this] () {
onAlarm();
}, true);
xwarn2(TSF"create ClientEventLoopConcrete!");
}
ClientEventLoopConcrete::~ClientEventLoopConcrete() {
m_alarm.reset();
#ifdef ANDROID
m_wakeupLock.reset();
#endif
xwarn2(TSF"destroy ClientEventLoopConcrete!");
stop();
xwarn2(TSF"destroy ClientEventLoopConcrete!");
}
int ClientEventLoopConcrete::AsyncCall(std::weak_ptr<ClientEventLoopCallback> callBack, const uint64_t &delay) {
std::lock_guard<std::mutex> _l(m_mutex);
if (m_exitFlag) {
xerror2(TSF"m_exitFlag is true!");
return -1;
}
auto ts = timeMs() + delay;
bool needSend = true;
if (!m_callBacks.empty()) {
if (m_callBacks.begin()->first < delay) {
needSend = false;
}
}
m_callBacks[ts].emplace_back(callBack);
if (needSend && (m_socketPair[0] > 0)) {
send(m_socketPair[0], "1", 1, 0);
}
return 0;
}
int ClientEventLoopConcrete::createSocketPair() {
destroySocketPair();
#ifdef WIN32
auto ret = evutil_socketpair(AF_INET, SOCK_STREAM, 0, m_socketPair);
#else
auto ret = evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, m_socketPair);
#endif
if (ret <

最低0.47元/天 解锁文章
1019

被折叠的 条评论
为什么被折叠?



