/** * 日期: 2025-03-08 * 作者: coffee * 描述: 毫秒级定时器, 最小堆实现, 中断/多线程安全 */ #include "HTimer.h" #include "HDLog.h" #include // 用于拷贝定时器文件使用可直接删除HDLog.h文件避免依赖 #ifndef LogD #define LogD(...) #endif // ==================== 原子操作支持 ==================== #if defined(__GNUC__) || defined(__clang__) // 支持 GCC 扩展 // 使用 __atomic_* 系列函数,提供明确的内存序语义 static inline int htimer_cas(volatile uint8_t *ptr, uint8_t oldv, uint8_t newv) { return __atomic_compare_exchange_n(ptr, &oldv, newv, 0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); } static inline void htimer_store(volatile uint8_t *ptr, uint8_t val) { __atomic_store_n(ptr, val, __ATOMIC_RELEASE); } #define HTIMER_CAS(ptr, oldv, newv) htimer_cas(ptr, oldv, newv) #define HTIMER_STORE(ptr, val) htimer_store(ptr, val) #define HTIMER_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) #define HTIMER_ATOMIC_OR(ptr, val) __atomic_fetch_or(ptr, val, __ATOMIC_RELEASE) #define HTIMER_ATOMIC_XCHG(ptr, val) __atomic_exchange_n(ptr, val, __ATOMIC_ACQ_REL) #define HTIMER_ATOMIC_LOAD(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE) #define HTIMER_RELEASE_FENCE() __atomic_thread_fence(__ATOMIC_RELEASE) #define HTIMER_ACQUIRE_FENCE() __atomic_thread_fence(__ATOMIC_ACQUIRE) #elif defined(_MSC_VER) #include #define HTIMER_CAS(ptr, oldv, newv) (_InterlockedCompareExchange8((volatile char*)(ptr), (char)(newv), (char)(oldv)) == (char)(oldv)) #define HTIMER_STORE(ptr, val) (*(ptr) = (val)) #define HTIMER_BARRIER() _ReadWriteBarrier() #define HTIMER_ATOMIC_OR(ptr, val) _InterlockedOr8((volatile char*)(ptr), (char)(val)) #define HTIMER_ATOMIC_XCHG(ptr, val) _InterlockedExchange8((volatile char*)(ptr), (char)(val)) #define HTIMER_ATOMIC_LOAD(ptr) (*(volatile uint8_t*)(ptr)) #define HTIMER_RELEASE_FENCE() _ReadWriteBarrier() #define HTIMER_ACQUIRE_FENCE() _ReadWriteBarrier() #else #pragma message("HTimer Not use atomic ops") static inline int htimer_cas_simple(volatile uint8_t *ptr, uint8_t oldv, uint8_t newv) { if (*ptr == oldv) { *ptr = newv; return 1; } return 0; } static inline uint8_t htimer_xchg_simple(volatile uint8_t *ptr, uint8_t newv) { uint8_t old = *ptr; *ptr = newv; return old; } #define HTIMER_CAS(ptr, oldv, newv) htimer_cas_simple(ptr, oldv, newv) #define HTIMER_STORE(ptr, val) (*(ptr) = (val)) #define HTIMER_BARRIER() ((void)0) #define HTIMER_ATOMIC_OR(ptr, val) (*(ptr) |= (val)) #define HTIMER_ATOMIC_XCHG(ptr, val) htimer_xchg_simple(ptr, val) #define HTIMER_ATOMIC_LOAD(ptr) (*(ptr)) #define HTIMER_RELEASE_FENCE() ((void)0) #define HTIMER_ACQUIRE_FENCE() ((void)0) #endif // 定时器内部状态 typedef enum { kTimerUnused = 0, ///< 未使用 kTimerAdding, ///< 添加中 (单核中断安全: 初始化字段期间) kTimerActive, ///< 活跃状态 kTimerDelete ///< 待删除 } eHTimerState; static uint32_t (*GetCurrentMs)(void); #define CHECK_VALUE (0x0FFFFFFF) #define CREATE_INDEX(id, index) ((id << 8) | index) #define GET_ID(index) ((index >> 8) & 0xFF) #define GET_INDEX(index) (index & 0xFF) #define HEAP_INVALID_INDEX (HTIMER_LEN_MAX) struct __attribute__((packed)) TimerInfo { TimeRegisterInfo *info; uint8_t infoLen; }; static struct TimerInfo sInfo; // ==================== 最小堆操作 ==================== // 堆使用 timers[i].heapMem 存储堆位置 i 处的定时器索引 // 注意:堆操作在 HTimerRun 中单线程执行,无需加锁 #define HEAP_AT(reg, heapIdx) ((reg)->timers[heapIdx].heapMem) #define HEAP_SET(reg, heapIdx, timerIdx) ((reg)->timers[heapIdx].heapMem = (timerIdx)) static inline HTimerInfo* getTimer(TimeRegisterInfo *reg, int heapIdx) { return ®->timers[HEAP_AT(reg, heapIdx)]; } static void heapSwap(TimeRegisterInfo *reg, int a, int b) { HTimerLen_t ta = HEAP_AT(reg, a); HTimerLen_t tb = HEAP_AT(reg, b); HEAP_SET(reg, a, tb); HEAP_SET(reg, b, ta); reg->timers[ta].heapIndex = b; reg->timers[tb].heapIndex = a; } static void heapUp(TimeRegisterInfo *reg, int i) { while (i > 0) { int p = (i - 1) >> 1; HTimerInfo *ti = getTimer(reg, i); HTimerInfo *tp = getTimer(reg, p); uint32_t iTime = ti->lastTime + ti->duration; uint32_t pTime = tp->lastTime + tp->duration; int32_t diff = (int32_t)(iTime - pTime); if (diff > 0) { break; } if (diff == 0 && HEAP_AT(reg, i) > HEAP_AT(reg, p)) { break; } heapSwap(reg, i, p); i = p; } } static void heapDown(TimeRegisterInfo *reg, int i) { int size = reg->heapSize; while (1) { int l = i * 2 + 1; int r = l + 1; int s = i; if (l < size) { HTimerInfo *tl = getTimer(reg, l); HTimerInfo *ts = getTimer(reg, s); int32_t diff = (int32_t)((tl->lastTime + tl->duration) - (ts->lastTime + ts->duration)); if (diff < 0 || (diff == 0 && HEAP_AT(reg, l) < HEAP_AT(reg, s))) { s = l; } } if (r < size) { HTimerInfo *tr = getTimer(reg, r); HTimerInfo *ts = getTimer(reg, s); int32_t diff = (int32_t)((tr->lastTime + tr->duration) - (ts->lastTime + ts->duration)); if (diff < 0 || (diff == 0 && HEAP_AT(reg, r) < HEAP_AT(reg, s))) { s = r; } } if (s == i) { break; } heapSwap(reg, i, s); i = s; } } static void heapPush(TimeRegisterInfo *reg, HTimerLen_t timerIdx) { if (reg->heapSize >= reg->len) { return; } HTimerLen_t i = reg->heapSize++; HEAP_SET(reg, i, timerIdx); reg->timers[timerIdx].heapIndex = i; heapUp(reg, i); } static HTimerLen_t heapPop(TimeRegisterInfo *reg) { if (reg->heapSize == 0) { return HEAP_INVALID_INDEX; } HTimerLen_t ret = HEAP_AT(reg, 0); reg->timers[ret].heapIndex = HEAP_INVALID_INDEX; if (--reg->heapSize > 0) { HEAP_SET(reg, 0, HEAP_AT(reg, reg->heapSize)); reg->timers[HEAP_AT(reg, 0)].heapIndex = 0; heapDown(reg, 0); } return ret; } // ==================== 定时器操作 ==================== static HTimer_t AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call, eHTimerFlags flags) { if (!GetCurrentMs) { LogD("GetCurrentMs not init"); return HTIMER_INVALID; } if (id >= sInfo.infoLen) { LogD("error id[%d]", id); return HTIMER_INVALID; } if ((duration & ~CHECK_VALUE) != 0) { LogD("duration overflow, duration[%d]", duration); return HTIMER_INVALID; } TimeRegisterInfo *reg = &sInfo.info[id]; uint32_t now = GetCurrentMs(); // 原子地查找并占用空闲槽位 for (HTimerLen_t i = 0; i < reg->len; ++i) { HTimerInfo *t = ®->timers[i]; // 第一步:CAS 原子占用,kTimerUnused -> kTimerAdding // 单核中断安全:即使中断发生,HTimerRun 也不会处理 kTimerAdding 状态 if (!HTIMER_CAS(&t->state, kTimerUnused, kTimerAdding)) { continue; } // 成功占用槽位,设置其他字段 #if HTIMER_USE_USERDATA t->userData = 0; #endif t->duration = duration; t->lastTime = now; t->call = call; t->flags = flags; t->heapIndex = HEAP_INVALID_INDEX; // 确保上述写入在状态变更前完成 HTIMER_RELEASE_FENCE(); // 第二步:kTimerAdding -> kTimerActive,标记初始化完成 HTIMER_STORE(&t->state, kTimerActive); // 标记需要调度 HTIMER_ATOMIC_OR(®->schedu, 1); return CREATE_INDEX(id, i); } // 槽位满,尝试紧急回收已删除的定时器 for (HTimerLen_t i = 0; i < reg->len; ++i) { HTimerInfo *t = ®->timers[i]; // 原子地将 kTimerDelete 转为 kTimerUnused if (!HTIMER_CAS(&t->state, kTimerDelete, kTimerUnused)) { continue; } // 回收成功,再次尝试占用 if (HTIMER_CAS(&t->state, kTimerUnused, kTimerAdding)) { #if HTIMER_USE_USERDATA t->userData = 0; #endif t->duration = duration; t->lastTime = now; t->call = call; t->flags = flags; t->heapIndex = HEAP_INVALID_INDEX; HTIMER_RELEASE_FENCE(); HTIMER_STORE(&t->state, kTimerActive); HTIMER_ATOMIC_OR(®->schedu, 1); return CREATE_INDEX(id, i); } } LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags); return HTIMER_INVALID; } void HTimerInitMs(uint32_t (*func)(void)) { GetCurrentMs = func; } uint32_t HTimerGetMs() { if (!GetCurrentMs) { return 0; } return GetCurrentMs(); } void HTimerInitRegister(TimeRegisterInfo *info, HTimerLen_t len) { memset(info, 0, sizeof(*info) * len); sInfo.info = info; sInfo.infoLen = len; } uint8_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen) { if (id >= sInfo.infoLen) { LogD("error id[%d], max[%d]", id, sInfo.infoLen); return 0; } if (infoLen > HTIMER_LEN_MAX) { LogD("infoLen too large, max 255"); return 0; } memset(info, 0, sizeof(*info) * infoLen); TimeRegisterInfo *reg = &sInfo.info[id]; reg->timers = info; reg->len = (HTimerLen_t)infoLen; reg->heapSize = 0; for (HTimerLen_t i = 0; i < infoLen; ++i) { info[i].heapIndex = HEAP_INVALID_INDEX; } return 1; } void HTimerRun(uint8_t id) { if (!GetCurrentMs || id >= sInfo.infoLen) { return; } TimeRegisterInfo *reg = &sInfo.info[id]; if (reg->run) { return ; } reg->run = 1; uint32_t now = GetCurrentMs(); // schedu 阶段:只有 HTimerRun 修改堆,单线程安全 // 使用 acquire-release 语义确保看到其他线程的写入 while (HTIMER_ATOMIC_XCHG(®->schedu, 0)) { // 确保看到 AddTimerData 中的写入 HTIMER_ACQUIRE_FENCE(); // 1. 清理堆中已删除的定时器 for (HTimerLen_t i = reg->heapSize; i > 0;) { i--; HTimerLen_t tIdx = HEAP_AT(reg, i); HTimerInfo *t = ®->timers[tIdx]; if (HTIMER_ATOMIC_LOAD(&t->state) == kTimerDelete) { HEAP_SET(reg, i, HEAP_AT(reg, --reg->heapSize)); t->heapIndex = HEAP_INVALID_INDEX; t->state = kTimerUnused; HTIMER_BARRIER(); if (i < reg->heapSize) { heapUp(reg, i); heapDown(reg, i); } } } // 2. 清理不在堆中的已删除定时器 + 添加活跃定时器 for (HTimerLen_t i = 0; i < reg->len; i++) { HTimerInfo *t = ®->timers[i]; uint8_t state = HTIMER_ATOMIC_LOAD(&t->state); if (state == kTimerDelete) { t->state = kTimerUnused; continue; } if (state == kTimerActive && t->heapIndex == HEAP_INVALID_INDEX) { heapPush(reg, i); } } } // 执行到期的定时器 while (reg->heapSize > 0) { HTimerLen_t tIdx = HEAP_AT(reg, 0); HTimerInfo *t = ®->timers[tIdx]; if (HTIMER_ATOMIC_LOAD(&t->state) == kTimerDelete) { heapPop(reg); t->state = kTimerUnused; t->heapIndex = HEAP_INVALID_INDEX; continue; } uint32_t triggerTime = t->lastTime + t->duration; if ((int32_t)(now - triggerTime) < 0) { break; } heapPop(reg); t->curr = 1; HTIMER_BARRIER(); if (t->call) { t->call(); } t->curr = 0; HTIMER_BARRIER(); if (HTIMER_ATOMIC_LOAD(&t->state) != kTimerActive) { continue; } t->lastTime = now; if (t->flags == kHTimerLoop) { heapPush(reg, tIdx); } else { t->state = kTimerDelete; HTIMER_ATOMIC_OR(®->schedu, 1); } } reg->run = 0; } HTimer_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags) { #ifdef HTIMER_CHECK_INVALID_LOOP HTimer_t result = AddTimerData(id, ms, call, flags); if (result == HTIMER_INVALID) { while (1); } return result; #else return AddTimerData(id, ms, call, flags); #endif } void HTimerRemove(HTimer_t index) { if (index == HTIMER_INVALID) { return; } uint8_t id = GET_ID(index); uint8_t i = GET_INDEX(index); if (id >= sInfo.infoLen) { return; } TimeRegisterInfo *reg = &sInfo.info[id]; if (i >= reg->len) { return; } HTimerInfo *t = ®->timers[i]; // 原子设置状态 uint8_t oldState; do { oldState = t->state; if (oldState == kTimerUnused) { return; // 已经删除 } } while (!HTIMER_CAS(&t->state, oldState, kTimerDelete)); // 标记需要调度 HTIMER_ATOMIC_OR(®->schedu, 1); } #if HTIMER_USE_USERDATA void HTimerSetUserData(HTimer_t index, long data) { if (index == HTIMER_INVALID) { return; } uint8_t id = GET_ID(index); uint8_t i = GET_INDEX(index); if (id >= sInfo.infoLen || i >= sInfo.info[id].len) { return; } sInfo.info[id].timers[i].userData = data; } long HTimerGetUserData(HTimer_t index) { if (index == HTIMER_INVALID) { return 0; } uint8_t id = GET_ID(index); uint8_t i = GET_INDEX(index); if (id >= sInfo.infoLen || i >= sInfo.info[id].len) { return 0; } return sInfo.info[id].timers[i].userData; } long HTimerGetCurrCallUserData(uint8_t id) { if (id >= sInfo.infoLen) { return 0; } TimeRegisterInfo *reg = &sInfo.info[id]; for (HTimerLen_t i = 0; i < reg->len; ++i) { if (reg->timers[i].curr) { return reg->timers[i].userData; } } return 0; } #endif