11#ifndef TIMER_USE_TIMERFD_EPOLL
13std::unordered_map<TimerId, TimerManager*> TimerManager::sTimerManagerMap;
14std::mutex TimerManager::sManagerMapMutex;
22#ifdef TIMER_USE_TIMERFD_EPOLL
24 mEpollFd = epoll_create1(EPOLL_CLOEXEC);
27 throw std::runtime_error(
"Failed to create epoll fd");
33 mTimerThread = std::thread(&TimerManager::timerThreadFunc,
this);
47 std::lock_guard<std::mutex> lock(mTimersMutex);
49 for (
auto& [
id, timerInfo] : mTimers) {
50#ifdef TIMER_USE_TIMERFD_EPOLL
53 timer_delete(timerInfo.timer);
55 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
56 sTimerManagerMap.erase(
id);
62#ifdef TIMER_USE_TIMERFD_EPOLL
63 if (mTimerThread.joinable()) {
78 bool periodic, std::atomic<bool>* cancelled) {
86 <<
" with delay " << delay_ms <<
"ms, periodic: " << periodic);
88#ifdef TIMER_USE_TIMERFD_EPOLL
90 int timer_fd = createTimerFd(delay_ms, periodic);
93 <<
": " << strerror(errno));
100 struct epoll_event ev;
104 if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, timer_fd, &ev) == -1) {
115 std::lock_guard<std::mutex> lock(mTimersMutex);
118 info.
callback = std::move(callback);
124 mTimers[id] = std::move(info);
133 std::lock_guard<std::mutex> lock(mTimersMutex);
135 info.timer = (timer_t)0;
137 info.
callback = std::move(callback);
143 mTimers[id] = std::move(info);
146 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
147 sTimerManagerMap[id] =
this;
151 timer_t timer = createSigevTimer(
id);
152 if (timer == (timer_t)-1) {
154 std::lock_guard<std::mutex> lock(mTimersMutex);
156 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
157 sTimerManagerMap.erase(
id);
163 std::lock_guard<std::mutex> lock(mTimersMutex);
164 mTimers[id].timer = timer;
168 updateSigevTimer(timer, delay_ms, periodic);
176#ifdef TIMER_USE_TIMERFD_EPOLL
178void TimerManager::timerThreadFunc() {
180 const int MAX_EVENTS = 64;
181 struct epoll_event events[MAX_EVENTS];
187 int nfds = epoll_wait(mEpollFd, events, MAX_EVENTS, 100);
190 if (errno == EINTR) {
191 TIMER_DEBUG(
"epoll_wait interrupted, continuing...");
202 for (
int i = 0; i < nfds; i++) {
203 TimerId id = events[i].data.u64;
206 bool shouldProcess =
false;
210 std::lock_guard<std::mutex> lock(mTimersMutex);
211 auto it = mTimers.find(
id);
212 if (it != mTimers.end()) {
214 if (it->second.cancelled && it->second.cancelled->load()) {
219 ssize_t bytes = read(it->second.fd, &exp,
sizeof(exp));
223 epoll_ctl(mEpollFd, EPOLL_CTL_DEL, it->second.fd,
nullptr);
224 close(it->second.fd);
229 timerInfo = it->second;
230 shouldProcess =
true;
237 ssize_t bytes = read(timerInfo.fd, &exp,
sizeof(exp));
239 <<
", expirations: " << exp);
242 if (timerInfo.cancelled && timerInfo.cancelled->load()) {
249 handleTimerExpired(timerInfo);
252 if (!timerInfo.periodic) {
263int TimerManager::createTimerFd(uint64_t delay_ms,
bool periodic) {
265 <<
"ms, periodic: " << periodic);
267 int timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
268 if (timer_fd == -1) {
273 struct itimerspec its;
274 its.it_value.tv_sec = delay_ms / 1000;
275 its.it_value.tv_nsec = (delay_ms % 1000) * 1000000;
278 its.it_interval = its.it_value;
280 <<
"s " << its.it_value.tv_nsec <<
"ns");
282 its.it_interval.tv_sec = 0;
283 its.it_interval.tv_nsec = 0;
285 <<
"s " << its.it_value.tv_nsec <<
"ns");
288 if (timerfd_settime(timer_fd, 0, &its,
nullptr) == -1) {
297void TimerManager::updateTimerFd(
int fd, uint64_t delay_ms,
bool periodic) {
299 <<
"ms, periodic: " << periodic);
301 struct itimerspec its;
302 its.it_value.tv_sec = delay_ms / 1000;
303 its.it_value.tv_nsec = (delay_ms % 1000) * 1000000;
306 its.it_interval = its.it_value;
308 its.it_interval.tv_sec = 0;
309 its.it_interval.tv_nsec = 0;
312 if (timerfd_settime(fd, 0, &its,
nullptr) == -1) {
320timer_t TimerManager::createSigevTimer(
TimerId id) {
324 sev.sigev_notify = SIGEV_THREAD;
325 sev.sigev_notify_function = &TimerManager::sigevTimerCallback;
326 sev.sigev_notify_attributes =
nullptr;
327 sev.sigev_value.sival_ptr =
reinterpret_cast<void*
>(id);
329 if (timer_create(CLOCK_MONOTONIC, &sev, &timer) == -1) {
337void TimerManager::updateSigevTimer(timer_t timer, uint64_t delay_ms,
bool periodic) {
338 struct itimerspec its;
339 its.it_value.tv_sec = delay_ms / 1000;
340 its.it_value.tv_nsec = (delay_ms % 1000) * 1000000;
343 its.it_interval = its.it_value;
345 <<
"s " << its.it_value.tv_nsec <<
"ns");
347 its.it_interval.tv_sec = 0;
348 its.it_interval.tv_nsec = 0;
350 <<
"s " << its.it_value.tv_nsec <<
"ns");
353 if (timer_settime(timer, 0, &its,
nullptr) == -1) {
358void TimerManager::sigevTimerCallback(sigval_t sv) {
366 std::lock_guard<std::mutex> lock(sManagerMapMutex);
367 auto it = sTimerManagerMap.find(
id);
368 if (it != sTimerManagerMap.end()) {
369 manager = it->second;
379 bool shouldProcess =
false;
382 std::lock_guard<std::mutex> lock(manager->mTimersMutex);
383 auto it = manager->mTimers.find(
id);
384 if (it != manager->mTimers.end()) {
386 if (it->second.cancelled && it->second.cancelled->load()) {
388 timer_delete(it->second.timer);
389 manager->mTimers.erase(it);
390 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
391 sTimerManagerMap.erase(
id);
395 timerInfo = it->second;
396 shouldProcess =
true;
399 if (!timerInfo.periodic) {
401 timer_delete(it->second.timer);
402 manager->mTimers.erase(it);
403 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
404 sTimerManagerMap.erase(
id);
410 manager->handleTimerExpired(timerInfo);
418 std::lock_guard<std::mutex> lock(mTimersMutex);
420 auto it = mTimers.find(
id);
421 if (it == mTimers.end()) {
426#ifdef TIMER_USE_TIMERFD_EPOLL
427 epoll_ctl(mEpollFd, EPOLL_CTL_DEL, it->second.fd,
nullptr);
428 close(it->second.fd);
430 timer_delete(it->second.timer);
431 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
432 sTimerManagerMap.erase(
id);
443 std::lock_guard<std::mutex> lock(mTimersMutex);
444 bool exists = mTimers.find(
id) != mTimers.end();
451 <<
" with delay " << delay_ms <<
"ms");
452 std::lock_guard<std::mutex> lock(mTimersMutex);
454 auto it = mTimers.find(
id);
455 if (it == mTimers.end()) {
461 if (it->second.cancelled) {
462 it->second.cancelled->store(
false);
465#ifdef TIMER_USE_TIMERFD_EPOLL
466 updateTimerFd(it->second.fd, delay_ms,
false);
468 updateSigevTimer(it->second.timer, delay_ms,
false);
471 it->second.interval_ms = delay_ms;
472 it->second.periodic =
false;
479 std::lock_guard<std::mutex> lock(mTimersMutex);
480 return mTimers.size();
485 std::lock_guard<std::mutex> lock(mTimersMutex);
487 auto it = mTimers.find(
id);
488 if (it != mTimers.end()) {
489 it->second.cancelled = newPtr;
496void TimerManager::handleTimerExpired(
const TimerInfo& timerInfo) {
500 if (timerInfo.cancelled && timerInfo.cancelled->load()) {
506 if (
auto looper = mLooper.lock()) {
507 TIMER_DEBUG_STREAM(
"Posting callback for timer " << timerInfo.id <<
" to main thread");
509 auto result = looper->post([callback = timerInfo.callback, cancelled = timerInfo.cancelled,
id = timerInfo.id]() {
510 TIMER_DEBUG_STREAM(
"Executing callback for timer " << id <<
" in main thread");
513 if (cancelled && cancelled->load()) {
514 TIMER_DEBUG_STREAM(
"Timer " << id <<
" cancelled in main thread, skipping");
520 TIMER_DEBUG_STREAM(
"Callback for timer " << id <<
" executed successfully");
521 } catch (
const std::exception& e) {
527 <<
" (future valid: " << result.valid() <<
")");
533void TimerManager::cleanupTimer(TimerId
id) {
535 std::lock_guard<std::mutex> lock(mTimersMutex);
536 auto it = mTimers.find(
id);
537 if (it != mTimers.end()) {
538#ifdef TIMER_USE_TIMERFD_EPOLL
539 epoll_ctl(mEpollFd, EPOLL_CTL_DEL, it->second.fd,
nullptr);
540 close(it->second.fd);
542 timer_delete(it->second.timer);
543 std::lock_guard<std::mutex> mapLock(sManagerMapMutex);
544 sTimerManagerMap.erase(
id);
Centralized debug and logging macros for SW Task Framework components.
#define TIMER_ERROR_STREAM(stream_expr)
Always-on error logging for TimerManager with stream expression.
#define TIMER_DEBUG(msg)
Conditional debug logging for TimerManager with simple message.
#define TIMER_INFO(msg)
Always-on info logging for TimerManager lifecycle events.
#define TIMER_ERROR(msg)
Always-on error logging for TimerManager critical issues.
#define TIMER_DEBUG_STREAM(stream_expr)
Conditional debug logging for TimerManager with stream expression.
Main event loop coordinator for asynchronous task management and timer operations.
High-performance timer management using Linux timerfd+epoll or sigev_thread.
TimerManager(std::weak_ptr< SLLooper > looper)
Construct a new TimerManager.
TimerId createTimer(std::function< void()> callback, uint64_t delay_ms, bool periodic, std::atomic< bool > *cancelled)
Create a new timer.
size_t getActiveTimerCount()
Get the number of currently active timers.
void updateCancelledPtr(TimerId id, std::atomic< bool > *newPtr)
Update the cancellation flag pointer for an existing timer.
~TimerManager()
Destroy the TimerManager and cleanup all resources.
static const char * getBackendName()
Get the name of the currently compiled timer backend.
bool hasTimer(TimerId id)
Check if a timer exists and is active.
bool restartTimer(TimerId id, uint64_t delay_ms)
Restart an existing timer with new delay.
bool cancelTimer(TimerId id)
Cancel an active timer.
Software Timer namespace containing all timer-related classes.
uint64_t TimerId
Unique identifier type for timer instances.
Internal timer information structure.
std::function< void()> callback
User callback function to execute on timer expiry.
TimerId id
Unique timer identifier.
int fd
timerfd file descriptor for Linux backend
uint64_t interval_ms
Timer interval in milliseconds.
std::atomic< bool > * cancelled
Pointer to cancellation flag (optional)
bool periodic
true for repeating timer, false for one-shot