C++ 线程在调用终止且没有活动异常的情况下退出

问题描述 投票:0回答:1

我创建了一个计时器类,用于创建和删除计时器,并且我有固定数量的计时器。有些计时器在完成回调函数后会重新启动。在某些情况下,我可能需要删除计时器。根据这个逻辑,我想出了以下代码:

定时器.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
。我似乎无法弄清楚为什么会出现错误。我脑海中浮现的事情基本上是,我在计时器到期后立即再次启动计时器,并且我需要在回调函数中进行一些清理以准备再次启动?另外,我是否应该在回调函数完成时加入线程?

c++ multithreading timer thread-safety
1个回答
0
投票

正如评论中提到的,当时间仍在运行但还没有

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

© www.soinside.com 2019 - 2024. All rights reserved.