Rob*_*son 1 c++ multithreading timer
我想要一个合理可靠的线程计时器,因此我编写了一个计时器对象,该对象在线程上触发std :: function。我希望此计时器能够在到达下一个刻度之前停止运行;:: sleep无法实现的功能(至少我不认为可以)。
所以我要做的是将条件变量放在互斥锁上。如果条件超时,我将触发该事件。如果发出条件信号,则退出线程。因此Stop方法需要能够使线程停止和/或中断其等待,我认为这是它现在正在做的事情。
但是,这有问题。有时线程不是joinable(),并且有时条件在超时后但进入等待状态之前发出信号。
我如何改善它并使之坚固?
以下是完整的仓库。这里的等待时间为10秒,但是程序应在创建Foo之后立即终止,然后立即销毁。有时会,但大多数时候不会。
#include <atomic>
#include <thread>
#include <future>
#include <sstream>
#include <chrono>
#include <iostream>
class Timer
{
public:
Timer() {}
~Timer()
{
Stop();
}
void Start(std::chrono::milliseconds const & interval, std::function<void(void)> const & callback)
{
Stop();
thread = std::thread([=]()
{
for(;;)
{
auto locked = std::unique_lock<std::mutex>(mutex);
auto result = terminate.wait_for(locked, interval);
if (result == std::cv_status::timeout)
{
callback();
}
else
{
return;
}
}
});
}
void Stop()
{
terminate.notify_one();
if(thread.joinable())
{
thread.join();
}
}
private:
std::thread thread;
std::mutex mutex;
std::condition_variable terminate;
};
class Foo
{
public:
Foo()
{
timer = std::make_unique<Timer>();
timer->Start(std::chrono::milliseconds(10000), std::bind(&Foo::Callback, this));
}
~Foo()
{
}
void Callback()
{
static int count = 0;
std::ostringstream o;
std::cout << count++ << std::endl;
}
std::unique_ptr<Timer> timer;
};
int main(void)
{
{
Foo foo;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
看到我的评论。您忘了实现线程正在等待的事物的状态,而互斥锁没有任何保护,线程也没有等待。条件变量是无状态的-您的代码必须跟踪您要通知线程的事物的状态。
这是固定的代码。请注意,互斥体保护stop,并且stop是线程正在等待的东西。
class Timer
{
public:
Timer() {}
~Timer()
{
Stop();
}
void Start(std::chrono::milliseconds const & interval,
std::function<void(void)> const & callback)
{
Stop();
{
auto locked = std::unique_lock<std::mutex>(mutex);
stop = false;
}
thread = std::thread([=]()
{
auto locked = std::unique_lock<std::mutex>(mutex);
while (! stop) // We hold the mutex that protects stop
{
auto result = terminate.wait_for(locked, interval);
if (result == std::cv_status::timeout)
{
callback();
}
}
});
}
void Stop()
{
{
// Set the predicate
auto locked = std::unique_lock<std::mutex>(mutex);
stop = true;
}
// Tell the thread the predicate has changed
terminate.notify_one();
if(thread.joinable())
{
thread.join();
}
}
private:
bool stop; // This is the thing the thread is waiting for
std::thread thread;
std::mutex mutex;
std::condition_variable terminate;
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2729 次 |
| 最近记录: |