Poco中的Event,是对C++11中mutex和conditional_variable做了一层封装,是它具有“Event”的概念。
Event应该有信号量机制,具有等待信号和set信号的行为。
所以看Poco的源码,可以看到对应的接口实现。
Event的内部成员:
private:
Event(const Event&);
Event& operator = (const Event&);
bool waitImpl(long milliseconds);
std::atomic<bool> _state; // 状态信号量
bool _autoreset; // 是否自动重置
mutable std::mutex _mutex;
std::condition_variable _cond;
wait相关函数
void Event::wait()
{
try
{
std::unique_lock<std::mutex> lock(_mutex);
while (!_state)
_cond.wait(lock, [this]() { return this->_state.load(); });
if (_autoreset) _state = false;
}
catch (std::system_error &e)
{
throw SystemException(e.what());
}
}
bool Event::waitImpl(long milliseconds)
{
try
{
std::unique_lock<std::mutex> lock(_mutex);
bool ret = _cond.wait_for(lock, std::chrono::milliseconds(milliseconds), [this]() { return this->_state.load(); });
if (ret && _autoreset) _state = false;
return ret;
}
catch (std::system_error &e)
{
throw SystemException(e.what());
}
}
inline void Event::wait(long milliseconds)
{
if (!waitImpl(milliseconds)) throw TimeoutException();
}
inline bool Event::tryWait(long milliseconds)
{
return waitImpl(milliseconds);
}
从源码可以看到,如果state为false,则通过conditional_variable等待信号。
如果设置了autoreset,则state=true后会立刻被重置回false。
这里有一点不明白,为什么atomic类型的还要加锁??
set相关函数
void Event::set()
{
try
{
std::lock_guard<std::mutex> lock(_mutex);
_state = true;
if (_autoreset) _cond.notify_one();
else _cond.notify_all();
}
catch (std::system_error &e)
{
throw SystemException(e.what());
}
}
void Event::reset()
{
try
{
std::lock_guard<std::mutex> lock(_mutex);
_state = false;
}
catch (std::system_error &e)
{
throw SystemException(e.what());
}
}
Event使用一个简单的示例
void notify1(Event& event) {
event.wait();
cout<<"You released notify1"<<endl;
}
void notify2(Event& event) {
event.wait();
cout<<"You released notify2"<<endl;
}
int main(int argc, char **argv) {
Event event;
cout << "[" << time_str() << "]begin to wait" << endl;
thread thread1(notify1, ref(event));
thread thread2(notify2, ref(event));
this_thread::sleep_for(chrono::milliseconds(200));
cout << "[" << time_str() << "]send singal" << endl;
event.set();
thread1.join();
thread2.join();
return 0;
}
执行结果为
为何不是两个都接收到信号呢? 因为Event初始化的时候,默认autoreset是true。也就是说一个信号收到后会立刻将state重置。
所以要稍微修改一下:
int main(int argc, char **argv) {
Event event(false); // <-----------------------false!
cout << "[" << time_str() << "]begin to wait" << endl;
thread thread1(notify1, ref(event));
thread thread2(notify2, ref(event));
this_thread::sleep_for(chrono::milliseconds(200));
cout << "[" << time_str() << "]send singal" << endl;
event.set();
thread1.join();
thread2.join();
return 0;
}
运行结果