SW Task Event Loop Framework v1.0.0
High-performance C++ asynchronous event loop framework with timer management and promise-based programming
Loading...
Searching...
No Matches
SLLooper.cpp
Go to the documentation of this file.
1
9 #include <cstring>
10 #include "SLLooper.h"
11 #include "Handler.h"
12 #include "Message.h"
13 #include "EventQueue.h"
14 #include "Debug.h"
15 #include <iostream>
16 #include <thread>
17 #include <string>
18 #include <atomic>
19 #include "TimerManager.h"
20 #include "Timer.h"
21 #include "Awaitable.h"
22
23 using namespace std;
24
25 namespace swt {
26
27 // ================= SLLooper Core Implementation =================
28
30 {
31 SLLOOPER_INFO("Constructor called");
32 mEventQueue = std::make_shared<EventQueue>();
33 mStarted = false;
34 t1 = std::thread(&SLLooper::loop, this);
35 SLLOOPER_INFO("Constructor finished");
36 }
37
39 if (!mTimerManager) {
40 SLLOOPER_DEBUG("Initializing TimerManager...");
41 try {
42 mTimerManager = std::make_unique<TimerManager>(weak_from_this());
43 SLLOOPER_DEBUG("TimerManager initialized successfully");
44 } catch (const std::exception& e) {
45 SLLOOPER_ERROR_STREAM("Failed to initialize TimerManager: " << e.what());
46 throw;
47 }
48 }
49 }
50
52 try {
53 SLLOOPER_INFO("Destructor called");
54 mStarted = false;
55 if (mTimerManager) {
56 SLLOOPER_DEBUG("Resetting TimerManager...");
57 mTimerManager.reset();
58 }
59 mEventQueue->quit();
60 if (t1.joinable()) {
61 if (std::this_thread::get_id() != t1.get_id()) {
62 t1.join();
63 } else {
64 t1.detach();
65 }
66 }
67 SLLOOPER_INFO("Destructor finished");
68 } catch (const std::exception& e) {
69 SLLOOPER_ERROR_STREAM("Exception in destructor: " << e.what());
70 } catch (...) {
71 SLLOOPER_ERROR("Unknown exception in destructor");
72 }
73 }
74
76 SLLOOPER_DEBUG("exit() called");
77 mStarted = false;
78 mEventQueue->quit();
79 SLLOOPER_DEBUG("exit() finished");
80 }
81
82 std::shared_ptr<EventQueue> SLLooper::getEventQueue() {
83 return mEventQueue;
84 }
85
87 {
88 try {
89 mStarted.store(true);
90 SLLOOPER_INFO("start looper");
91
92 int loop_count = 0;
93 while (mStarted.load()) {
94 loop_count++;
95 auto item = mEventQueue->pollNext();
96
97 if (!item) {
98 if (SLLOOPER_DEBUG_ENABLED && loop_count % 50 == 0) {
99 SLLOOPER_DEBUG_STREAM("pollNext timeout (cycle " << loop_count << ")");
100 }
101 if (mEventQueue->isQuit()) {
102 break;
103 } else {
104 continue;
105 }
106 }
107
108 SLLOOPER_DEBUG_STREAM("Processing item (cycle " << loop_count
109 << ", type: " << (int)item->type << ")");
110
111 auto& itemRef = item.value();
112 if (itemRef.type == EventQueue::QueueItemType::MESSAGE) {
113 SLLOOPER_DEBUG("Processing message");
114 if (itemRef.message && itemRef.message->mHandler) {
115 itemRef.message->mHandler->dispatchMessage(itemRef.message);
116 }
117 } else if (itemRef.type == EventQueue::QueueItemType::FUNCTION) {
118 SLLOOPER_DEBUG_STREAM("Executing function, task valid: " << itemRef.task.valid());
119 if (itemRef.task.valid()) {
120 try {
121 itemRef.task();
122 SLLOOPER_DEBUG("Function executed successfully");
123 } catch (const std::exception& e) {
124 SLLOOPER_ERROR_STREAM("Exception in function execution: " << e.what());
125 }
126 }
127 }
128
129 std::this_thread::sleep_for(std::chrono::milliseconds(1));
130 }
131
132 SLLOOPER_INFO("Exited main loop");
133
134 } catch (const std::exception& e) {
135 SLLOOPER_ERROR_STREAM("Exception in loop: " << e.what());
136 }
137
138 mStarted.store(false);
139 SLLOOPER_INFO("Loop finished");
140 return false;
141 }
142
143 // ========== TIMER API IMPLEMENTATIONS ==========
144
145 Timer SLLooper::addTimer(std::function<void()> callback, uint64_t delay_ms) {
146 SLLOOPER_DEBUG_STREAM("addTimer called with delay " << delay_ms << "ms");
147 if (!callback) {
148 SLLOOPER_ERROR("callback is null!");
149 return Timer(0, weak_from_this());
150 }
152 Timer timer(0, weak_from_this());
153 TimerId id = createTimerInternal(std::move(callback), delay_ms, false, &timer.mCancelled);
154 if (id == 0) {
155 SLLOOPER_ERROR("Failed to create timer!");
156 return timer;
157 }
158 timer.mId = id;
159 SLLOOPER_DEBUG_STREAM("Created timer with ID " << id << ", active: " << timer.isActive());
160 return timer;
161 }
162
163 Timer SLLooper::addPeriodicTimer(std::function<void()> callback, uint64_t interval_ms) {
164 SLLOOPER_DEBUG_STREAM("addPeriodicTimer called with interval " << interval_ms << "ms");
165 if (!callback) {
166 SLLOOPER_ERROR("callback is null!");
167 return Timer(0, weak_from_this());
168 }
170 Timer timer(0, weak_from_this());
171 TimerId id = createTimerInternal(std::move(callback), interval_ms, true, &timer.mCancelled);
172 if (id == 0) {
173 SLLOOPER_ERROR("Failed to create periodic timer!");
174 return timer;
175 }
176 timer.mId = id;
177 SLLOOPER_DEBUG_STREAM("Created periodic timer with ID " << id << ", active: " << timer.isActive());
178 return timer;
179 }
180
181 void SLLooper::updateTimerCancelledPtr(TimerId id, std::atomic<bool>* newPtr) {
182 SLLOOPER_DEBUG_STREAM("Updating cancelled pointer for timer " << id);
183 if (mTimerManager) {
184 mTimerManager->updateCancelledPtr(id, newPtr);
185 } else {
186 SLLOOPER_ERROR("TimerManager is null in updateTimerCancelledPtr!");
187 }
188 }
189
190 TimerId SLLooper::createTimerInternal(std::function<void()> callback, uint64_t delay_ms,
191 bool periodic, std::atomic<bool>* cancelled) {
192 SLLOOPER_DEBUG_STREAM("createTimerInternal called with delay " << delay_ms
193 << "ms, periodic: " << periodic);
194 if (!mTimerManager) {
195 SLLOOPER_DEBUG("TimerManager is null, initializing...");
197 }
198 if (!mTimerManager) {
199 SLLOOPER_ERROR("TimerManager still null after initialization!");
200 return 0;
201 }
202 TimerId id = mTimerManager->createTimer(std::move(callback), delay_ms, periodic, cancelled);
203 SLLOOPER_DEBUG_STREAM("createTimerInternal returning ID " << id);
204 return id;
205 }
206
208 SLLOOPER_DEBUG_STREAM("cancelTimerInternal called for ID " << id);
209 if (!mTimerManager) {
210 SLLOOPER_ERROR("TimerManager is null in cancelTimerInternal!");
211 return false;
212 }
213 bool result = mTimerManager->cancelTimer(id);
214 SLLOOPER_DEBUG_STREAM("cancelTimerInternal result: " << result);
215 return result;
216 }
217
219 if (!mTimerManager) return false;
220 return mTimerManager->hasTimer(id);
221 }
222
223 bool SLLooper::restartTimerInternal(TimerId id, uint64_t delay_ms) {
224 SLLOOPER_DEBUG_STREAM("restartTimerInternal called for ID " << id
225 << " with delay " << delay_ms << "ms");
226 if (!mTimerManager) {
227 SLLOOPER_ERROR("TimerManager is null in restartTimerInternal!");
228 return false;
229 }
230 bool result = mTimerManager->restartTimer(id, delay_ms);
231 SLLOOPER_DEBUG_STREAM("restartTimerInternal result: " << result);
232 return result;
233 }
234
236 if (!mTimerManager) {
237 return 0;
238 }
239 size_t count = mTimerManager->getActiveTimerCount();
240 return count;
241 }
242
243 // ================== Awaitable Implementations ===================
244
245 // DelayAwaitable
246void DelayAwaitable::await_suspend(std::coroutine_handle<> handle) const noexcept {
247 auto self = const_cast<DelayAwaitable*>(this);
248 SLLOOPER_DEBUG_STREAM("DelayAwaitable: Starting delay for " << mDelayMs << "ms");
249 mLooper->postDelayed(mDelayMs, [self, handle]() {
250 SLLOOPER_DEBUG("DelayAwaitable: Delay completed, resuming coroutine");
251 self->setReady();
252 handle.resume();
253 });
254}
255
256// WorkAwaitable generic template
257template<typename T>
258void WorkAwaitable<T>::await_suspend(std::coroutine_handle<> handle) const noexcept {
259 auto self = const_cast<WorkAwaitable*>(this);
260 SLLOOPER_DEBUG("WorkAwaitable: Starting background work");
261 std::thread([self, handle]() {
262 try {
263 auto result = self->getFunc()();
264 self->setResult(result);
265 SLLOOPER_DEBUG("WorkAwaitable: Work completed successfully with result");
266 } catch (const std::exception& e) {
267 SLLOOPER_ERROR_STREAM("WorkAwaitable: Exception in background work: " << e.what());
268 self->setException(std::current_exception());
269 } catch (...) {
270 SLLOOPER_ERROR("WorkAwaitable: Unknown exception in background work");
271 self->setException(std::current_exception());
272 }
273 self->getLooper()->post([handle]() {
274 SLLOOPER_DEBUG("WorkAwaitable: Resuming coroutine on main thread");
275 handle.resume();
276 });
277 }).detach();
278}
279
280// ✅ ĐÚNG SYNTAX cho specialization - KHÔNG có template<>
281void WorkAwaitable<void>::await_suspend(std::coroutine_handle<> handle) const noexcept {
282 auto self = const_cast<WorkAwaitable<void>*>(this);
283 SLLOOPER_DEBUG("WorkAwaitable<void>: Starting background work");
284 std::thread([self, handle]() {
285 try {
286 self->getFunc()();
287 self->setResult();
288 SLLOOPER_DEBUG("WorkAwaitable<void>: Work completed successfully");
289 } catch (const std::exception& e) {
290 SLLOOPER_ERROR_STREAM("WorkAwaitable<void>: Exception: " << e.what());
291 self->setException(std::current_exception());
292 } catch (...) {
293 SLLOOPER_ERROR("WorkAwaitable<void>: Unknown exception");
294 self->setException(std::current_exception());
295 }
296 self->getLooper()->post([handle]() {
297 SLLOOPER_DEBUG("WorkAwaitable<void>: Resuming coroutine on main thread");
298 handle.resume();
299 });
300 }).detach();
301}
302
303// PostAwaitable generic template
304template<typename T>
305void PostAwaitable<T>::await_suspend(std::coroutine_handle<> handle) const noexcept {
306 auto self = const_cast<PostAwaitable<T>*>(this);
307 SLLOOPER_DEBUG("PostAwaitable: Posting to main thread");
308 mLooper->post([self, handle]() {
309 try {
310 auto result = self->getFunc()();
311 self->setResult(result);
312 SLLOOPER_DEBUG("PostAwaitable: Function executed successfully with result");
313 } catch (const std::exception& e) {
314 SLLOOPER_ERROR_STREAM("PostAwaitable: Exception: " << e.what());
315 self->setException(std::current_exception());
316 } catch (...) {
317 SLLOOPER_ERROR("PostAwaitable: Unknown exception");
318 self->setException(std::current_exception());
319 }
320 SLLOOPER_DEBUG("PostAwaitable: Resuming coroutine");
321 handle.resume();
322 });
323}
324
325// ✅ ĐÚNG SYNTAX cho specialization - KHÔNG có template<>
326void PostAwaitable<void>::await_suspend(std::coroutine_handle<> handle) const noexcept {
327 auto self = const_cast<PostAwaitable<void>*>(this);
328 SLLOOPER_DEBUG("PostAwaitable<void>: Posting to main thread");
329 mLooper->post([self, handle]() {
330 try {
331 self->getFunc()();
332 self->setResult();
333 SLLOOPER_DEBUG("PostAwaitable<void>: Function executed successfully");
334 } catch (const std::exception& e) {
335 SLLOOPER_ERROR_STREAM("PostAwaitable<void>: Exception: " << e.what());
336 self->setException(std::current_exception());
337 } catch (...) {
338 SLLOOPER_ERROR("PostAwaitable<void>: Unknown exception");
339 self->setException(std::current_exception());
340 }
341 SLLOOPER_DEBUG("PostAwaitable<void>: Resuming coroutine");
342 handle.resume();
343 });
344}
345
346// Template class instantiations
347template class WorkAwaitable<int>;
348template class WorkAwaitable<std::string>;
349template class WorkAwaitable<double>;
350template class WorkAwaitable<bool>;
351template class WorkAwaitable<long>;
352template class WorkAwaitable<float>;
353
354template class PostAwaitable<int>;
355template class PostAwaitable<std::string>;
356template class PostAwaitable<double>;
357template class PostAwaitable<bool>;
358template class PostAwaitable<long>;
359template class PostAwaitable<float>;
360
361} // namespace swt
Direct awaitable types for coroutine integration with SLLooper.
Centralized debug and logging macros for SW Task Framework components.
#define SLLOOPER_DEBUG_ENABLED
Enable/disable debug output for SLLooper operations.
Definition Debug.h:42
#define SLLOOPER_INFO(msg)
Always-on info logging for SLLooper lifecycle events.
Definition Debug.h:253
#define SLLOOPER_DEBUG_STREAM(stream_expr)
Conditional debug logging for SLLooper with stream expression.
Definition Debug.h:210
#define SLLOOPER_ERROR(msg)
Always-on error logging for SLLooper critical issues.
Definition Debug.h:230
#define SLLOOPER_DEBUG(msg)
Conditional debug logging for SLLooper operations.
Definition Debug.h:191
#define SLLOOPER_ERROR_STREAM(stream_expr)
Always-on error logging for SLLooper with stream expression.
Definition Debug.h:238
Unified event queue supporting messages and functions with timed execution.
Main event loop coordinator for asynchronous task management and timer operations.
High-performance timer management using Linux timerfd+epoll or sigev_thread.
RAII timer wrapper with move semantics for safe timer management.
Awaitable for delay operations.
Definition Awaitable.h:208
void await_suspend(std::coroutine_handle<> handle) const noexcept
Suspend coroutine and start timer.
Definition SLLooper.cpp:246
@ FUNCTION
Function task with std::packaged_task.
@ MESSAGE
Traditional message with handler.
Awaitable for executing function on main thread.
Definition Awaitable.h:275
void await_suspend(std::coroutine_handle<> handle) const noexcept
Suspend coroutine and post to main thread.
Definition SLLooper.cpp:305
void updateTimerCancelledPtr(TimerId id, std::atomic< bool > *newPtr)
Update timer cancellation pointer for moved Timer objects.
Definition SLLooper.cpp:181
bool restartTimerInternal(TimerId id, uint64_t delay_ms)
Restart existing timer with new delay.
Definition SLLooper.cpp:223
Timer addTimer(std::function< void()> callback, uint64_t delay_ms)
Add one-shot timer with millisecond precision.
Definition SLLooper.cpp:145
std::shared_ptr< EventQueue > getEventQueue()
Get access to the underlying event queue.
Definition SLLooper.cpp:82
~SLLooper()
Destructor - stops event loop and cleanup resources.
Definition SLLooper.cpp:51
bool cancelTimerInternal(TimerId id)
Internal timer cancellation method.
Definition SLLooper.cpp:207
Timer addPeriodicTimer(std::function< void()> callback, uint64_t interval_ms)
Add periodic timer with millisecond interval.
Definition SLLooper.cpp:163
bool loop()
Run one iteration of the event loop.
Definition SLLooper.cpp:86
void exit()
Request event loop to exit.
Definition SLLooper.cpp:75
void initializeTimerManager()
Initialize TimerManager lazily.
Definition SLLooper.cpp:38
TimerId createTimerInternal(std::function< void()> callback, uint64_t delay_ms, bool periodic, std::atomic< bool > *cancelled)
Internal timer creation method.
Definition SLLooper.cpp:190
size_t getActiveTimerCount()
Get count of active timers.
Definition SLLooper.cpp:235
SLLooper()
Constructor - initializes message queue and starts event loop.
Definition SLLooper.cpp:29
bool hasTimerInternal(TimerId id)
Check if timer exists in internal management.
Definition SLLooper.cpp:218
RAII timer wrapper with boost-style API and move semantics.
Definition Timer.h:68
bool isActive() const
Check if timer is currently active.
Definition Timer.cpp:75
Awaitable for executing work on background thread.
Definition Awaitable.h:43
void await_suspend(std::coroutine_handle<> handle) const noexcept
Suspend coroutine and execute work on background thread.
Definition SLLooper.cpp:258
Software Timer namespace containing all timer-related classes.
Definition Awaitable.h:21
uint64_t TimerId
Unique identifier type for timer instances.
Definition Timer.h:25