WaitForSingleObject()およびWaitForMultipleObjects()と同じセマンティクスを持つ関数を介してチェックできるWin32リセットイベントを彷彿とさせるメカニズムが必要です(現時点では..SingleObject()バージョンのみが必要です)。しかし、私は複数のプラットフォームをターゲットにしているので、私が持っているのはboost :: threads(AFAIK)だけです。私は次のクラスを思いついたので、潜在的な問題について、そしてそれがタスクに任されているかどうかについて質問したいと思いました。前もって感謝します。
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;
}
};
使用例;
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;
}
編集
MichaelBurrの提案に従ってコードを修正しました。私の「非常に単純な」テストは問題がないことを示しています。
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;
}
};