我如何通知运行libevent的线程它应该采取一些行动?
How can I inform a thread running libevent that it should take some action?
我在后台线程中使用libevent来运行hiredis并订阅远程redis数据库。使用另一个SO问题的简单示例,订阅效果非常好:
招聘人员等待消息
然而,为了避免竞争条件,在主线程中添加订阅是很重要的。为了实现这一点,我创建了一个std::vector<std::string>
对象,其中包含后端应该订阅的任何密钥字符串。从这个vector对象中读取数据是通过互斥体来完成的。
但是,我如何通知后端我已经添加了一些订阅?目前我使用的计时器设置为一个非常低的分辨率:
void Client::fireAndRequeueTimer(int fd, short e, void* arg)
{
Client* client = reinterpret_cast<Client*>(arg); // the client handles the subscription to redis (via hiredis/libevent)
if (client->mDisconnect)
return; // the main thread wants us to exit, so we don't recreate the timer
event* ev = &client->mTimerEvent; // some timer event object we created
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1000; // 1ms
evtimer_add(ev, &tv);
// mPendingSubscriptions is an std::vector of strings, which contain the keys that we should add subscriptions to.
if (client->mPendingSubscriptions.size())
{
std::unique_lock<std::mutex> lock(client->mSubscriptionsMutex);
do
{
redisAsyncCommand(
client->mContext,
Client::subCallback,
(char*)"sub",
"SUBSCRIBE %s",
client->mPendingSubscriptions.back().c_str());
client->mPendingSubscriptions.pop_back();
}
while (client->mPendingSubscriptions.size());
}
}
(注意,我使用的是libevent 1.4.x
,所以EV_PERSIST等功能不存在,我必须在每个事件中重新创建计时器)。
虽然上面的工作,我不满意,原因如下:
- 它给后端带来了不必要的压力来持续轮询向量。
- 如果没有大量的注释,读者很难理解
- 慢;这个计时器将使订阅事件所需的时间增加1ms。这可能很重要,也可能不重要,但无论如何,这都是浪费时间。
是否有解决这个问题的方法,可以在libevent 1.4.x
的范围内解决这些问题?
我个人更喜欢让目标线程在它的事件队列中添加一个eventfd
(或类似的构造)。
eventfd
可以被任何其他线程安全地通知,并导致目标线程调用相关的事件处理程序。
这样,您就不需要担心正确锁定libevent结构的绝对最小值,因为操作系统会为您处理这个问题。
注意:eventfd
在OSX上不可用,但只要您不需要极高的事件率,可以很容易地用管道模拟。
相关文章:
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- C++ Poco - 如何向特定线程发送通知/消息?
- C++ - 如何不错过来自多个线程的多个通知?
- C++ - std::condition_variable 由不同的线程通知
- 线程启动延迟 - 通知所有未唤醒所有线程
- 使用 condition_variable::notify_all 通知多个线程
- 通知所有在多线程C++不起作用.导致死锁
- 通知线程是否始终需要在修改期间锁定共享数据
- 当子线程退出时,如何通知父线程
- QSocketNotifier:不能从另一个线程启用或禁用套接字通知程序
- 使用Berkeley套接字的线程通知
- 通知有关变量变化的线程(信号?)
- 用信号通知线程启动特定的函数
- 线程退出时通知Waiters
- C++11 std::condition_variable:我们可以将锁直接传递给通知的线程吗?
- 通知线程退出
- std::condition_variable - 等待多个线程通知观察者
- CreateTimerQueue() 线程从何而来
- 线程销毁通知
- 在C++中执行跨平台线程间通知的好方法是什么?