Ring Daemon 16.0.0
Loading...
Searching...
No Matches
threadloop.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 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
21#include <ciso646> // fix windows compiler bug
22
23namespace jami {
24
25void
26ThreadLoop::mainloop(std::thread::id& tid,
27 const std::function<bool()> setup,
28 const std::function<void()> process,
29 const std::function<void()> cleanup)
30{
31 tid = std::this_thread::get_id();
32 try {
33 if (setup()) {
34 while (state_ == ThreadState::RUNNING)
35 process();
36 cleanup();
37 } else {
38 JAMI_ERR("setup failed");
39 }
40 } catch (const ThreadLoopException& e) {
41 JAMI_ERR("[threadloop:%p] ThreadLoopException: %s", this, e.what());
42 } catch (const std::exception& e) {
43 JAMI_ERR("[threadloop:%p] Unwaited exception: %s", this, e.what());
44 }
45 stop();
46}
47
48ThreadLoop::ThreadLoop(const std::function<bool()>& setup,
49 const std::function<void()>& process,
50 const std::function<void()>& cleanup)
51 : setup_(setup)
52 , process_(process)
53 , cleanup_(cleanup)
54 , thread_()
55{}
56
58{
59 if (isRunning()) {
60 JAMI_ERR("join() should be explicitly called in owner's destructor");
61 join();
62 }
63}
64
65void
67{
68 const auto s = state_.load();
69
70 if (s == ThreadState::RUNNING) {
71 JAMI_ERR("already started");
72 return;
73 }
74
75 // stop pending but not processed by thread yet?
76 if (s == ThreadState::STOPPING and thread_.joinable()) {
77 JAMI_DBG("stop pending");
78 thread_.join();
79 }
80
81 state_ = ThreadState::RUNNING;
82 thread_ = std::thread(&ThreadLoop::mainloop, this, std::ref(threadId_), setup_, process_, cleanup_);
83 threadId_ = thread_.get_id();
84}
85
86void
88{
90 state_.compare_exchange_strong(expected, ThreadState::STOPPING);
91}
92
93void
95{
96 stop();
97 if (thread_.joinable())
98 thread_.join();
99}
100
101void
103{
104 if (thread_.joinable())
105 thread_.join();
106}
107
108void
110{
111 stop();
112 throw ThreadLoopException();
113}
114
115bool
117{
118#ifdef _WIN32
119 return state_ == ThreadState::RUNNING;
120#else
121 return thread_.joinable() and state_ == ThreadState::RUNNING;
122#endif
123}
124
125void
127{
129 cv_.notify_one();
130}
131} // 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:218
#define JAMI_DBG(...)
Definition logger.h:216
void emitSignal(Args... args)
Definition ring_signal.h:64