我创建了一个计时器类,用于创建和删除计时器,并且我有固定数量的计时器。有些计时器在完成回调函数后会重新启动。在某些情况下,我可能需要删除计时器。根据这个逻辑,我想出了以下代码:
定时器.cpp:
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <vector>
#include <algorithm>
#include <iostream>
#include <thread>
#include <atomic>
class Timer
{
public:
Timer();
~Timer();
void Start( const uint8_t pipeId, const uint32_t msPeriod);
void Stop();
private:
void TimerCallbacktimer( const uint8_t pipeId);
std::chrono::milliseconds msPeriod_;
uint8_t pipeId_;
std::thread thread_;
std::condition_variable cv_;
std::mutex mutex_;
std::atomic<bool> stop_waiting_{false};
std::atomic<bool> done_{false};
};
void Timer::TimerCallbacktimer( const uint8_t pipeId)
{
//callback function left empty on purpose
}
void Timer::Start( const uint8_t pipeId, const uint32_t msPeriod)
{
pipeId_ = pipeId;
msPeriod_ = std::chrono::milliseconds(msPeriod);
if (done_) //if the thread was already created and expired join it before restarting the thread
{
thread_.join();
done_.store(false);
}
thread_ = std::thread
{
[this]()
{
std::unique_lock<std::mutex> lck(mutex_);
cv_.wait_for(lck, msPeriod_, [this]() { return stop_waiting_.load(); });
if (not stop_waiting_)
{
TimerCallbacktimer(pipeId_);
done_.store(true);
}
}
};
}
void Timer::Stop()
{
stop_waiting_.store(true);
cv_.notify_one();
}
Timer::Timer()
{
}
Timer::~Timer()
{
if (thread_.joinable())
{
thread_.join();
}
}
std::vector<Timer> TimerArray(30);
std::mutex timerMutex;
void CreateTimer( const uint8_t slot , const int32_t pipeId, const uint32_t msPeriod )
{
std::unique_lock<std::mutex> lock(timerMutex);
TimerArray[slot].Start(pipeId, msPeriod);
}
void DeleteTimer( const uint8_t slot )
{
std::unique_lock<std::mutex> lock(timerMutex);
TimerArray[slot].Stop();
}
int main(int argc, char const *argv[])
{
CreateTimer(3, 3, 300);
CreateTimer(4, 3, 100);
DeleteTimer(4);
CreateTimer(3, 3, 100);
// sometimes I start the same timer immediately after it has called its callback function
CreateTimer(3, 3, 100);
return 0;
}
由于我确实有固定数量的计时器,因此在完成后我会再次调用同一个计时器 我面临的问题是有时会出现错误
terminate called without an active exception
。我似乎无法弄清楚为什么会出现错误。我脑海中浮现的事情基本上是,我在计时器到期后立即再次启动计时器,并且我需要在回调函数中进行一些清理以准备再次启动?另外,我是否应该在回调函数完成时加入线程?
正如评论中提到的,当时间仍在运行但还没有
Start
时,您不处理调用 done_
的情况。
要重新启动计时器,您可以向
stop_waiting_
、join
发出信号(并将 done_
重置为其初始值):
//if (done_) //if the thread was already created and expired join it before restarting the thread
if (thread_.joinable()){
stop_waiting_.store(true);
thread_.join();
done_.store(false);
}
现场演示.
代码中的崩溃是由
thread_ = std::thread ...
在加入之前引起的。它与这个非常简化的代码有同样的问题:
int main() {
std::thread t{[](){
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}};
}
t
的析构函数将在之前没有 std::terminate
时调用 join
。