I need some mechanism reminiscent of Win32 reset events that I can check via functions having the same semantics with WaitForSingleObject() and WaitForMultipleObjects() (Only need the ..SingleObject() version for the moment) . But I am targeting multiple platforms so all I have is boost::threads (AFAIK) . I came up with the following class and wanted to ask about the potential problems and whether it is up to the task or not. Thanks in advance.
class reset_event
{
bool flag, auto_reset;
boost::condition_variable cond_var;
boost::mutex mx_flag;
public:
reset_event(bool _auto_reset = false) : flag(false), auto_reset(_auto_reset)
{
}
void wait()
{
boost::unique_lock<boost::mutex> LOCK(mx_flag);
if (flag)
return;
cond_var.wait(LOCK);
if (auto_reset)
flag = false;
}
bool wait(const boost::posix_time::time_duration& dur)
{
boost::unique_lock<boost::mutex> LOCK(mx_flag);
bool ret = cond_var.timed_wait(LOCK, dur) || flag;
if (auto_reset && ret)
flag = false;
return ret;
}
void set()
{
boost::lock_guard<boost::mutex> LOCK(mx_flag);
flag = true;
cond_var.notify_all();
}
void reset()
{
boost::lock_guard<boost::mutex> LOCK(mx_flag);
flag = false;
}
};
Example usage;
reset_event terminate_thread;
void fn_thread()
{
while(!terminate_thread.wait(boost::posix_time::milliseconds(10)))
{
std::cout << "working..." << std::endl;
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}
std::cout << "thread terminated" << std::endl;
}
int main()
{
boost::thread worker(fn_thread);
boost::this_thread::sleep(boost::posix_time::seconds(1));
terminate_thread.set();
worker.join();
return 0;
}
EDIT
I have fixed the code according to Michael Burr's suggestions. My "very simple" tests indicate no problems.
class reset_event
{
bool flag, auto_reset;
boost::condition_variable cond_var;
boost::mutex mx_flag;
public:
explicit reset_event(bool _auto_reset = false) : flag(false), auto_reset(_auto_reset)
{
}
void wait()
{
boost::unique_lock<boost::mutex> LOCK(mx_flag);
if (flag)
{
if (auto_reset)
flag = false;
return;
}
do
{
cond_var.wait(LOCK);
} while(!flag);
if (auto_reset)
flag = false;
}
bool wait(const boost::posix_time::time_duration& dur)
{
boost::unique_lock<boost::mutex> LOCK(mx_flag);
if (flag)
{
if (auto_reset)
flag = false;
return true;
}
bool ret = cond_var.timed_wait(LOCK, dur);
if (ret && flag)
{
if (auto_reset)
flag = false;
return true;
}
return false;
}
void set()
{
boost::lock_guard<boost::mutex> LOCK(mx_flag);
flag = true;
cond_var.notify_all();
}
void reset()
{
boost::lock_guard<boost::mutex> LOCK(mx_flag);
flag = false;
}
};