diff --git a/src/scheduled_executor.cpp b/src/scheduled_executor.cpp index f33f996b28e898c9c7a014a6336fc92257c101a6..e3566007c2cc34f28f6ef80c9478ff212e057d5a 100644 --- a/src/scheduled_executor.cpp +++ b/src/scheduled_executor.cpp @@ -23,8 +23,12 @@ namespace jami { ScheduledExecutor::ScheduledExecutor() - : thread_([this] { - while (running_.load()) + : running_(std::make_shared<std::atomic<bool>>(true)) + , thread_([this, is_running = running_] { + // The thread needs its own reference of `running_` in case the + // scheduler is destroyed within the thread because of a job + + while (*is_running) loop(); }) {} @@ -32,8 +36,17 @@ ScheduledExecutor::ScheduledExecutor() ScheduledExecutor::~ScheduledExecutor() { stop(); - if (thread_.joinable()) + + if (not thread_.joinable()) { + return; + } + + // Avoid deadlock + if (std::this_thread::get_id() == thread_.get_id()) { + thread_.detach(); + } else { thread_.join(); + } } void @@ -41,7 +54,7 @@ ScheduledExecutor::stop() { { std::lock_guard<std::mutex> lock(jobLock_); - running_ = false; + *running_ = false; jobs_.clear(); } cv_.notify_all(); @@ -106,7 +119,7 @@ ScheduledExecutor::loop() std::vector<Job> jobs; { std::unique_lock<std::mutex> lock(jobLock_); - while (running_ and (jobs_.empty() or jobs_.begin()->first > clock::now())) { + while (*running_ and (jobs_.empty() or jobs_.begin()->first > clock::now())) { if (jobs_.empty()) cv_.wait(lock); else { @@ -114,7 +127,7 @@ ScheduledExecutor::loop() cv_.wait_until(lock, nextJob); } } - if (not running_) + if (not *running_) return; jobs = std::move(jobs_.begin()->second); jobs_.erase(jobs_.begin()); diff --git a/src/scheduled_executor.h b/src/scheduled_executor.h index b65a56d63c577af86cd99723c03e40824a019494..532c4d9f101dc42d0af747ce3bbb15db18f41f88 100644 --- a/src/scheduled_executor.h +++ b/src/scheduled_executor.h @@ -137,7 +137,7 @@ private: void schedule(std::shared_ptr<Task>, time_point t); void reschedule(std::shared_ptr<RepeatedTask>, time_point t, duration dt); - std::atomic_bool running_ {true}; + std::shared_ptr<std::atomic<bool>> running_; std::map<time_point, std::vector<Job>> jobs_ {}; std::mutex jobLock_ {}; std::condition_variable cv_ {};