Ring Daemon
Loading...
Searching...
No Matches
threadloop.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "threadloop.h"
19#include "logger.h"
20
21namespace jami {
22
23void
24ThreadLoop::mainloop(std::thread::id& tid,
25 const std::function<bool()>& setup,
26 const std::function<void()>& process,
27 const std::function<void()>& cleanup)
28{
29 tid = std::this_thread::get_id();
30 try {
31 if (setup()) {
32 while (state_ == ThreadState::RUNNING)
33 process();
34 cleanup();
35 } else {
36 JAMI_ERR("setup failed");
37 }
38 } catch (const ThreadLoopException& e) {
39 JAMI_ERR("[threadloop:%p] ThreadLoopException: %s", this, e.what());
40 } catch (const std::exception& e) {
41 JAMI_ERR("[threadloop:%p] Unwaited exception: %s", this, e.what());
42 }
43 stop();
44}
45
46ThreadLoop::ThreadLoop(const std::function<bool()>& setup,
47 const std::function<void()>& process,
48 const std::function<void()>& cleanup)
49 : setup_(setup)
50 , process_(process)
51 , cleanup_(cleanup)
52 , thread_()
53{}
54
56{
57 if (isRunning()) {
58 JAMI_ERR("join() should be explicitly called in owner's destructor");
59 join();
60 }
61}
62
63void
65{
66 const auto s = state_.load();
67
68 if (s == ThreadState::RUNNING) {
69 JAMI_ERR("already started");
70 return;
71 }
72
73 // stop pending but not processed by thread yet?
74 if (s == ThreadState::STOPPING and thread_.joinable()) {
75 JAMI_DBG("stop pending");
76 thread_.join();
77 }
78
79 state_ = ThreadState::RUNNING;
80 thread_ = std::thread(&ThreadLoop::mainloop, this, std::ref(threadId_), setup_, process_, cleanup_);
81 threadId_ = thread_.get_id();
82}
83
84void
86{
88 state_.compare_exchange_strong(expected, ThreadState::STOPPING);
89}
90
91void
93{
94 stop();
95 if (thread_.joinable())
96 thread_.join();
97}
98
99void
101{
102 if (thread_.joinable())
103 thread_.join();
104}
105
106void
108{
109 stop();
110 throw ThreadLoopException();
111}
112
113bool
115{
116#ifdef _WIN32
117 return state_ == ThreadState::RUNNING;
118#else
119 return thread_.joinable() and state_ == ThreadState::RUNNING;
120#endif
121}
122
123void
125{
127 cv_.notify_one();
128}
129} // namespace jami
bool isRunning() const noexcept
virtual ~ThreadLoop()
ThreadLoop(const std::function< bool()> &setup, const std::function< void()> &process, const std::function< void()> &cleanup)
virtual void stop()
#define JAMI_ERR(...)
Definition logger.h:230
#define JAMI_DBG(...)
Definition logger.h:228
void emitSignal(Args... args)
Definition jami_signal.h:64