基于小根堆的定时器优化请求:替换/修复POSIX定时器死锁问题
实现思路
- 用列表存储定时器信息,按定时时间从小到大排序,选取定时最短的首个元素作为核心定时器的定时时长
- 回调时重新排序列表以选取新的定时时长,即每个线程仅维护一个核心定时器,但列表中存储多个定时器信息
- 要求回调函数与核心定时器处于同一线程
现有问题
- 采用POSIX定时器作为核心定时器,使用信号通知机制,但信号处理函数中需调用非异步信号安全函数,导致莫名死锁
- 在信号处理函数中重置定时器
SetTimer时,每次都会阻塞在timer_create处,其他线程不受影响
现有代码
bool posixThreadTimerEx::SetTimer(INT_64 nElapse) { if (nElapse <= 0) { return false; } std::cout << "1"; KillTimer(); std::cout << "5"; memset(&m_sigev, 0, sizeof(m_sigev)); m_sigev.sigev_notify = SIGEV_SIGNAL; // 使用信号通知 m_sigev.sigev_signo = m_signalNum; // 实时信号方式 m_sigev.sigev_value.sival_ptr = this; std::cout << "6"; memset(&m_its, 0, sizeof(m_its)); m_its.it_value.tv_sec = nElapse / 1000; m_its.it_value.tv_nsec = (nElapse % 1000) * 1000000; m_its.it_interval.tv_sec = 0; m_its.it_interval.tv_nsec = 0; std::cout << "7"; if (timer_create(CLOCK_REALTIME, &m_sigev, &m_timerID) == -1) { int err = errno; DIR_WARN("timer_create err is %d", err); // DSSKEYUI_ERR("timer_create error"); return false; } std::cout << "8"; if (timer_settime(m_timerID, 0, &m_its, NULL) == -1) { int err = errno; DIR_WARN("timer_settime err is %d", err); // DSSKEYUI_ERR("timer_settime error"); return false; } std::cout << "9"; m_nElapse = nElapse; std::cout << "0" << std::endl; return true; } bool posixThreadTimerEx::KillTimer() { if (m_nElapse <= 0) { return false; } std::cout << "2"; if (timer_delete(m_timerID) == -1) { int err = errno; DIR_WARN("timer_delete err is %d", err); // DSSKEYUI_ERR("Kill Error"); return false; } m_timerID = nullptr; std::cout << "3"; m_nElapse = 0; std::cout << "4"; return true; }
需求
寻求可替代当前POSIX定时器的新方案,或对现有实现进行优化,使定时器到期后的回调函数与核心定时器处于同一线程,且避免莫名死锁。
内容的提问来源于stack exchange,提问作者zhihong yan
相关产品推荐
相关产品推荐

