由于目前c++标准中没有现成的定时器,本设计使用c++11相关语法并进行封装。
本定时器包含一个timermanager类用于创建定时器和进行定时任务管理,timermanager会创建两个线程(mtimertickthread、mtimercallbackthread)分别用于时间处理和函数回调。
可以使用timermanager的create方法创建多个定时器,每次创建的定时器id会累加,并返回itimer类型的共享指针。其中itimer类中定义了start和stop方法,用于启动或停止当前定时器。
timermanager还有一个内部类timermessagequeue用于实现定时器消息的插入、删除与定时控制。
关键类型及接口介绍timermessage类型作为通信的元素类型using timercallback = std::function;
struct timermessage {
const int id; // time id.
const long long timeout; // time out value.
const timercallback callback; // timeout callback function.
const timertype type; // 0:once, 1:periodic.
long long when; // time out occure time.
bool valid; // set true when timeout and pop from message queue.
timermessage()
: id(0), timeout(0), callback(nullptr), type(once_timer), when(0), valid(false)
{}
timermessage(const int &id, const long long &timeout, const timercallback &callback,
const timertype &type = once_timer)
: id(id), timeout(timeout), callback(callback), type(type), when(0), valid(false)
{}
};()>
id、timeout、callback、type伴随着timer的生命周期,一旦创建不可修改。
when、valid为辅助信息,在消息流转过程中适时变化。
timermanager的create方法std::shared_ptr create(const long long &timeoutmillis, const timercallback &callback,
const timertype &type = timertype_once);
用于创建定时器,有三个参数,分别是定时时长(单位毫秒),超时callback用于定时器到期的回调函数,定时器类型(单次还是循环定时器)。
定时器类的start、stop方法bool start(void);
void stop(void);
start时会向timermessagequeue中插入消息,该消息包括定时器id、超时时间timeout、回调函数callback、定时器类型type、到期时间when,插入时按when进行排序(二分法、复杂度为log2n);
stop时会依据id从timermessagequeue中删除消息,并将valid设置为false,防止继续callback;
在重复start时会先stop原来的定时器再重新start,到期时间以最后一次start的时间为准。
核心逻辑介绍timermessagequeue的插入与删除实现,确保消息能高效的按序插入对应位置。bool enqueuemessage(const timermessagerefptr &message, const long long &when)
{
do {
std::lock_guard lg(mmuxlock);
mmapidwhens[message->id].push_back(when);
logd(add message id:%d, when:%lld, message->id, when);
message->when = when;
mmessages.insert(
std::upper_bound(mmessages.begin(), mmessages.end(), when,
[](const long long &when, const timermessagerefptr &m) {
return (when when);
}),
message);
} while (0);
mcond.notify_one();
std::this_thread::yield();
return true;
}
void removemessages(const int &id)
{
std::lock_guard lg(mmuxlock);
auto it = mmapidwhens.find(id);
if (it == mmapidwhens.end()) {
return;
}
for (auto const &when : it->second) {
logd(del message id:%d, when:%lld, id, when);
mmessages.erase(
std::remove_if(
std::lower_bound(mmessages.begin(), mmessages.end(), when,
[](const timermessagerefptr &m, const long long &when) {
return (m->when id)); }),
mmessages.end());
}
mmapidwhens.erase(id);
}
bool hasmessages(const int &id) const
{
std::lock_guard lg(mmuxlock);
bool ret = (mmapidwhens.end() != mmapidwhens.find(id));
logv(has message id:%d %s, id, ret ? yes : no);
return ret;
}
std::lower_bound和std::upper_bound用于在有序的容器中快速查找可插入位置(不小于目标值和不大于目标值的位置)迭代器。
取出定时器到期消息mtimertickthread用于从mtimertickqueue中取出到期的定时器消息。
如果没有到期消息则会休眠等待,等待的时间是最近要到期的时间与当前时间差,并且可以随时被打断(当有新的消息插入时会打断);
由于消息插入时是按到期时间排序插入的,所以每次取出的都是最近要到期的那一条定时消息。
inline void waitforitems(void)
{
std::unique_lock ul(mmuxlock);
mcond.wait(ul, [this]() { return !mmessages.empty(); });
if (0 == mmessages.front()->when) {
return;
}
long long waitingtimemicros = 0;
while (!mmessages.empty()
&& (waitingtimemicros = mmessages.front()->when - steadytimemicros()) > 0) {
// next message is not ready, set a timeout to wake up when it is ready.
mcond.wait_for(ul, std::chrono::microseconds(waitingtimemicros));
}
}
inline timermessagerefptr next(void)
{
while (true) {
waitforitems();
do {
std::lock_guard lg(mmuxlock); // minimise the lock scope.
if (!mmessages.empty()
&& (steadytimemicros() >= mmessages.front()->when)) { // time is up.
timermessagerefptr msg = std::move(mmessages.front());
mmessages.pop_front();
msg->valid = true;
// remove message by id and when from map.
auto &whens = mmapidwhens[msg->id];
whens.erase(std::remove_if(whens.begin(), whens.end(),
[&msg](const long long &when) {
return when == msg->when;
}),
whens.end());
if (whens.empty()) {
mmapidwhens.erase(msg->id);
}
logd(pop message id:%d, when:%lld, msg->id, msg->when);
return msg;
}
} while (0);
}
}
处理定时器到期消息mtimertickthread从mtimertickqueue中取出到期的定时器消息后,再插入mcallbackqueue中,供mtimercallbackthread线程调用回调函数完成定时器超时回调通知。
如果是循环定时器,则将定时消息的到期时间when加上超时时间timeout后重新插入mtimertickqueue中,继续进行对应消息的流转。
do {
auto message = mtimertickqueue->next();
if (!message) {
continue;
}
if (!message->callback) {
// no callback is a magic identifier for the quit message.
break;
}
do {
std::unique_lock ul(mmutexlock);
if (!message->valid) {
break;
}
if (periodic_timer == message->type) {
(void)mtimertickqueue->enqueuemessage(message,
message->when + message->timeout);
}
(void)mcallbackqueue->push_back(message);
ul.unlock();
mcond.notify_one();
std::this_thread::yield();
} while (0);
} while (mmainthreadalive);
回调定时器回调函数mtimercallbackthread线程从mcallbackqueue中取出消息并调用回调函数完成定时器超时回调通知。
timermessagerefptr message = nullptr;
do {
std::unique_lock ul(mmutexlock);
mcond.wait(ul, [this]() { return !mcallbackqueue->empty(); });
message = mcallbackqueue->front();
mcallbackqueue->pop_front();
if (!message) {
continue;
}
if (!message->callback) {
// no callback is a magic identifier for the quit message.
break;
}
if (!message->valid) {
continue;
}
// handler dispatch message.
logv(callback message id:%d, when:%lld, message->id, message->when);
message->callback();
ul.unlock();
std::this_thread::yield();
} while (mmainthreadalive);
使用步骤举例1.create timer manager instance
auto timermgr = mdtimer::timermanager::getinstance();
2.create timer instance
auto timer1 = timermgr->create(50, std::bind(timeoutcallback, once timer1, 50ms));
auto timer2 = timermgr->create(100, std::bind(timeoutcallback, periodic timer2, 100ms),
mdtimer::periodic_timer);
3.start timer
(void)timer1->start();
(void)timer2->start();
4.stop timer
timer1->stop();
timer2->stop();
参考代码定时器实现/*
* copyright (c) 2023 . all rights reserved.
*
* file name : mdtimer.hpp
* author : longbin
* created date: 2020-05-07 21:54:42
* description : message driven timer
*
*/
#ifndef __mdtimer_hpp__
#define __mdtimer_hpp__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef log_tag
# undef log_tag
#endif // log_tag
#define log_tag mdtimer
#include logging.hpp
// usage:
// 1. create timer manager instance;
// auto timermgr = mdtimer::timermanager::getinstance();
// 2. create timer instance;
// auto timer1 = timermgr -> create(50, std::bind(timeoutcallback, once timer1, 50ms));
// auto timer2 = timermgr -> create(100, std::bind(timeoutcallback, periodic timer2, 100ms),
// mdtimer::periodic_timer);
// 3. start timer;
// (void)timer1->start();
// (void)timer2->start();
// 4. stop timer;
// timer1->stop();
// timer2->stop();
namespace mdtimer
{
using timertype = enum timertype { once_timer = 0, periodic_timer = 1 };
class itimer
{
public:
virtual ~itimer() = default;
virtual bool start(void) = 0;
virtual void stop(void) = 0;
}; // class itimer
class timermanager : public std::enable_shared_from_this
{
private:
using timercallback = std::function;
class timermessage;
using timermessagerefptr = std::shared_ptr;
using timermessagerefptrlist = std::deque;
using timermanagerrefptr = std::shared_ptr;
struct timermessage {
const int id; // time id.
const long long timeout; // time out value.
const timercallback callback; // timeout callback function.
const timertype type; // 0:once, 1:periodic.
long long when; // time out occure time.
bool valid; // set true when timeout and pop from message queue.
timermessage()
: id(0), timeout(0), callback(nullptr), type(once_timer), when(0), valid(false)
{}
timermessage(const int &id, const long long &timeout, const timercallback &callback,
const timertype &type = once_timer)
: id(id), timeout(timeout), callback(callback), type(type), when(0), valid(false)
{}
};
class timermessagequeue
{
private:
constexpr static bool mshowmessages = false;
timermessagerefptrlist mmessages{};
std::map> mmapidwhens;
mutable std::mutex mmuxlock;
std::condition_variable mcond;
private:
timermessagequeue(const timermessagequeue &) = delete;
timermessagequeue &operator=(const timermessagequeue &) = delete;
inline void showmessages()
{
std::string queue{};
std::for_each(mmessages.begin(), mmessages.end(),
[&queue](const timermessagerefptr &m) {
queue += std::to_string(m->id) + : + std::to_string(m->when) + ;
});
logd(show messages (size:%zu) %s, mmessages.size(), queue.c_str());
}
inline void waitforitems(void)
{
std::unique_lock ul(mmuxlock);
mcond.wait(ul, [this]() { return !mmessages.empty(); });
if (0 == mmessages.front()->when) {
return;
}
long long waitingtimemicros = 0;
while (!mmessages.empty()
&& (waitingtimemicros = mmessages.front()->when - steadytimemicros()) > 0) {
// next message is not ready, set a timeout to wake up when it is ready.
mcond.wait_for(ul, std::chrono::microseconds(waitingtimemicros));
}
}
public:
timermessagequeue() = default;
virtual ~timermessagequeue() = default;
timermessagerefptr next(void)
{
while (true) {
waitforitems();
do {
std::lock_guard lg(mmuxlock); // minimise the lock scope.
if (!mmessages.empty()
&& (steadytimemicros() >= mmessages.front()->when)) { // time is up.
timermessagerefptr msg = std::move(mmessages.front());
mmessages.pop_front();
msg->valid = true;
// remove message by id and when from map.
auto &whens = mmapidwhens[msg->id];
whens.erase(std::remove_if(whens.begin(), whens.end(),
[&msg](const long long &when) {
return when == msg->when;
}),
whens.end());
if (whens.empty()) {
mmapidwhens.erase(msg->id);
}
logd(pop message id:%d, when:%lld, msg->id, msg->when);
return msg;
}
} while (0);
}
}
bool enqueuemessage(const timermessagerefptr &message, const long long &when)
{
do {
std::lock_guard lg(mmuxlock);
mmapidwhens[message->id].push_back(when);
logd(add message id:%d, when:%lld, message->id, when);
message->when = when;
mmessages.insert(
std::upper_bound(mmessages.begin(), mmessages.end(), when,
[](const long long &when, const timermessagerefptr &m) {
return (when when);
}),
message);
if (mshowmessages) {
showmessages();
}
} while (0);
mcond.notify_one();
std::this_thread::yield();
return true;
}
void removemessages(const int &id)
{
std::lock_guard lg(mmuxlock);
auto it = mmapidwhens.find(id);
if (it == mmapidwhens.end()) {
return;
}
for (auto const &when : it->second) {
logd(del message id:%d, when:%lld, id, when);
mmessages.erase(
std::remove_if(
std::lower_bound(mmessages.begin(), mmessages.end(), when,
[](const timermessagerefptr &m, const long long &when) {
return (m->when id)); }),
mmessages.end());
}
mmapidwhens.erase(id);
if (mshowmessages) {
showmessages();
}
}
bool hasmessages(const int &id) const
{
std::lock_guard lg(mmuxlock);
bool ret = (mmapidwhens.end() != mmapidwhens.find(id));
logv(has message id:%d %s, id, ret ? yes : no);
return ret;
// return mmessages.end()
// != std::find_if(mmessages.begin(), mmessages.end(),
// [&id](const timermessagerefptr &m) { return ((id == m->id));
// });
}
}; // class timermessagequeue
class timerimpl : public itimer
{
friend class timermanager; // to access its private start/stop
private:
timermanagerrefptr mtimermanager = nullptr;
timermessagerefptr mtimermessage = nullptr;
public:
explicit timerimpl(const timermanagerrefptr &manager, const int &id,
const long long &timeoutmillis, const timercallback &callback,
const timertype &type)
{
logi(create timer id:%d, timeout:%lldms, type:%d, id, timeoutmillis, type);
mtimermanager = manager;
mtimermessage =
std::make_shared(id, timeoutmillis * 1000, callback, type);
}
virtual ~timerimpl()
{
logi(destroy timer id:%d, mtimermessage->id);
this->stop(); // if destroy timer manager before timer the stop will be blocked.
}
virtual bool start(void) override
{
mtimermessage->when = mtimermessage->timeout + steadytimemicros();
return mtimermanager ? mtimermanager->start(mtimermessage) : false;
}
virtual void stop(void) override
{
if (mtimermanager) {
mtimermanager->stop(mtimermessage);
}
}
}; // class timerimpl
public:
virtual ~timermanager()
{
logd(~timermanager);
mmainthreadalive = false;
(void)mcallbackqueue->push_back(std::make_shared());
mcond.notify_all();
(void)mtimertickqueue->enqueuemessage(std::make_shared(), 0);
(void)mtimertickqueue->enqueuemessage(std::make_shared(), -1);
if (mtimertickthread.joinable()) {
mtimertickthread.join();
}
if (mtimercallbackthread.joinable()) {
mtimercallbackthread.join();
}
}
static std::shared_ptr getinstance(void)
{
static std::shared_ptr instance =
std::shared_ptr(new timermanager());
return instance;
}
std::shared_ptr create(const long long &timeoutmillis, const timercallback &callback,
const timertype &type = once_timer)
{
int id = mtimerid.fetch_add(1);
return std::shared_ptr(
new timerimpl(shared_from_this(), id, timeoutmillis, callback, type));
}
static long long steadytimemicros(void)
{
auto now = std::chrono::time_point_cast(
std::chrono::steady_clock::now());
std::chrono::microseconds span =
std::chrono::duration_cast(now.time_since_epoch());
return span.count();
}
private:
timermanager(const timermanager &) = delete;
timermanager &operator=(const timermanager &) = delete;
timermanager() : mmainthreadalive(true)
{
mtimertickthread = std::thread([this]() {
do {
auto message = mtimertickqueue->next();
if (!message) {
continue;
}
if (!message->callback) {
// no callback is a magic identifier for the quit message.
break;
}
do {
std::unique_lock ul(mmutexlock);
if (!message->valid) {
break;
}
if (periodic_timer == message->type) {
(void)mtimertickqueue->enqueuemessage(message,
message->when + message->timeout);
}
(void)mcallbackqueue->push_back(message);
ul.unlock();
mcond.notify_one();
std::this_thread::yield();
} while (0);
} while (mmainthreadalive);
logi(timertickthread exit.);
});
mtimercallbackthread = std::thread([this]() {
timermessagerefptr message = nullptr;
do {
std::unique_lock ul(mmutexlock);
mcond.wait(ul, [this]() { return !mcallbackqueue->empty(); });
message = mcallbackqueue->front();
mcallbackqueue->pop_front();
if (!message) {
continue;
}
if (!message->callback) {
// no callback is a magic identifier for the quit message.
break;
}
if (!message->valid) {
continue;
}
// handler dispatch message.
logv(callback message id:%d, when:%lld, message->id, message->when);
message->callback();
ul.unlock();
std::this_thread::yield();
} while (mmainthreadalive);
logi(timercallbackthread exit.);
});
}
inline bool start(const timermessagerefptr &message)
{
std::lock_guard lg(mmutexlock);
logi(start timer id:%d, timeout:%lldms, message->id, message->timeout / 1000);
// stop the exist timer then start.
if (mtimertickqueue->hasmessages(message->id)) {
mtimertickqueue->removemessages(message->id);
}
mcallbackqueue->erase(std::remove_if(mcallbackqueue->begin(), mcallbackqueue->end(),
[&message](const timermessagerefptr &m) {
return ((message->id == m->id));
}),
mcallbackqueue->end());
message->valid = false;
return mtimertickqueue->enqueuemessage(message, message->when);
}
inline void stop(const timermessagerefptr &message)
{
std::lock_guard lg(mmutexlock);
logi(stop timer id:%d, message->id);
if (mtimertickqueue->hasmessages(message->id)) {
mtimertickqueue->removemessages(message->id);
}
mcallbackqueue->erase(std::remove_if(mcallbackqueue->begin(), mcallbackqueue->end(),
[&message](const timermessagerefptr &m) {
return ((message->id == m->id));
}),
mcallbackqueue->end());
message->valid = false;
}
private:
std::atomic mtimerid{1};
std::shared_ptr mtimertickqueue = std::make_shared();
std::shared_ptr> mcallbackqueue =
std::make_shared>();
std::atomic mmainthreadalive{true};
std::thread mtimertickthread;
std::thread mtimercallbackthread;
mutable std::mutex mmutexlock;
std::condition_variable mcond;
}; // class timermanager
}; // namespace mdtimer
#endif //__mdtimer_hpp__,>()>
定时器使用例子/*****************************************
* copyright (c) 2020 * ltd. all rights reserved.
* file name : mdtimertest.cpp
* created date: 2020-05-07 00:35:00
*******************************************/
#include
#include
#include
#include
#include
// #include callstack.h
#include mdtimer.hpp
#ifdef log_tag
# undef log_tag
#endif // log_tag
#define log_tag mdtimertest
#include logging.hpp
static void timeoutcallback(const std::string &info)
{
logi(timeoutcallback: %s, info.c_str());
}
void signal_segv_handler(int signo)
{
loge(caught signal: %d, signo);
// callstack_dump(callstack);
/* reset signal handle to default */
(void)signal(signo, sig_dfl);
/* will receive sigsegv again and exit app */
}
int main()
{
(void)signal(sigsegv, signal_segv_handler);
auto timermgr = mdtimer::timermanager::getinstance();
if (timermgr == nullptr) {
loge(error: create timer failed.);
return -1;
}
// std::this_thread::sleep_for(std::chrono::seconds(3));
auto timer1 = timermgr->create(50, std::bind(timeoutcallback, once timer1, 50ms));
(void)timer1->start();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
timer1->stop();
//周期性执行定时任务
auto timer2 = timermgr->create(100, std::bind(timeoutcallback, periodic timer2, 100ms),
mdtimer::periodic_timer);
(void)timer2->start();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
timer2->stop();
//周期性执行定时任务
auto timer3 = timermgr->create(1000, std::bind(timeoutcallback, periodic timer3, 1000ms),
mdtimer::periodic_timer);
(void)timer3->start();
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
(void)timer1->start();
(void)timer2->start();
(void)timer3->start();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
timer1->stop();
timer2->stop();
timer3->stop();
#if 1
auto timer4 = timermgr->create(20, std::bind(timeoutcallback, periodic timer4, 20ms),
mdtimer::periodic_timer);
(void)timer4->start();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
timer4->stop();
#endif
#if 0
auto timer5 = timermgr->create(10, std::bind(timeoutcallback, periodic timer5, 10ms),
mdtimer::periodic_timer);
for (auto i = 0; i start();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
timer5->stop();
// std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
#endif
logi(the end.);
return 0;
}
运行log2023-06-12 14:10:13.374461 13360 13360 i mdtimer:191 create timerimpl id:1, timeout:50, type:0
2023-06-12 14:10:13.374531 13360 13360 i mdtimer:329 start id:1, timeout:50ms
2023-06-12 14:10:13.425528 13360 13362 i mdtimertest:25 timeoutcallback: timer1: once, 50ms
2023-06-12 14:10:13.475776 13360 13360 i mdtimer:344 stop id:1
2023-06-12 14:10:13.475813 13360 13360 i mdtimer:191 create timerimpl id:2, timeout:100, type:1
2023-06-12 14:10:13.475817 13360 13360 i mdtimer:329 start id:2, timeout:100ms
2023-06-12 14:10:13.577174 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:13.687436 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:13.778635 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:13.876929 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:13.976795 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:14.076345 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:14.177249 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:14.276597 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:14.376828 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:14.476367 13360 13360 i mdtimer:344 stop id:2
2023-06-12 14:10:14.476445 13360 13360 i mdtimer:191 create timerimpl id:3, timeout:1000, type:1
2023-06-12 14:10:14.476460 13360 13360 i mdtimer:329 start id:3, timeout:1000ms
2023-06-12 14:10:15.477362 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:16.477212 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:17.477276 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:18.477688 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:19.476631 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:19.476740 13360 13360 i mdtimer:329 start id:1, timeout:50ms
2023-06-12 14:10:19.476775 13360 13360 i mdtimer:329 start id:2, timeout:100ms
2023-06-12 14:10:19.476784 13360 13360 i mdtimer:329 start id:3, timeout:1000ms
2023-06-12 14:10:19.527071 13360 13362 i mdtimertest:25 timeoutcallback: timer1: once, 50ms
2023-06-12 14:10:19.576829 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:19.676966 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:19.777616 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:19.877071 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:19.978404 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.076912 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.177797 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.277207 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.377493 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.477006 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.477045 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:20.577124 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.677249 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.777554 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.878031 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:20.977304 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:21.076999 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:21.177763 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:21.277001 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:21.377242 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:21.477678 13360 13362 i mdtimertest:25 timeoutcallback: timer2: periodic, 100ms
2023-06-12 14:10:21.477737 13360 13362 i mdtimertest:25 timeoutcallback: timer3: periodic, 1000ms
2023-06-12 14:10:21.479624 13360 13360 i mdtimer:344 stop id:1
2023-06-12 14:10:21.479692 13360 13360 i mdtimer:344 stop id:2
2023-06-12 14:10:21.479707 13360 13360 i mdtimer:344 stop id:3
2023-06-12 14:10:21.479718 13360 13360 i mdtimer:191 create timerimpl id:4, timeout:20, type:1
2023-06-12 14:10:21.479730 13360 13360 i mdtimer:329 start id:4, timeout:20ms
2023-06-12 14:10:21.499973 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.520535 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.540938 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.560465 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.584846 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.600391 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.619945 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.640485 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.661126 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.680551 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.700040 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.720451 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.741117 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.761350 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.780723 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.803386 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.820695 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.840791 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.860119 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.880511 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.900001 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.920576 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.941140 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.960555 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:21.980128 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.000512 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.019996 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.040414 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.060041 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.080564 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.099851 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.122287 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.140901 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.160394 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.179968 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.200225 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.220663 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.239965 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.260511 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.280020 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.305578 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.320103 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.340671 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.360015 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.380570 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.401000 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.420479 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.439866 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.460528 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.479953 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.500648 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.520394 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.540747 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.561312 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.580095 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.600382 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.620899 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.640418 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.659902 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.680163 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.703046 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.720542 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.740724 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.760168 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.780537 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.800054 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.820631 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.840785 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.860125 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.881097 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.900537 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.920620 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.941611 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.960467 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.979897 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:22.999982 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.020105 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.040916 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.060492 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.079993 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.100434 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.120644 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.140971 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.160481 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.181060 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.201456 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.222556 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.239880 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.260501 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.280484 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.299980 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.321099 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.340601 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.360090 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.380639 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.400425 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.422625 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.440473 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.460980 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.480272 13360 13362 i mdtimertest:25 timeoutcallback: timer4: periodic, 20ms
2023-06-12 14:10:23.481266 13360 13360 i mdtimer:344 stop id:4
2023-06-12 14:10:23.481313 13360 13360 i mdtimertest:88 the end.
2023-06-12 14:10:23.481323 13360 13360 i mdtimer:203 destroy timerimpl id:4
2023-06-12 14:10:23.481329 13360 13360 i mdtimer:344 stop id:4
2023-06-12 14:10:23.481336 13360 13360 i mdtimer:203 destroy timerimpl id:3
2023-06-12 14:10:23.481341 13360 13360 i mdtimer:344 stop id:3
2023-06-12 14:10:23.481348 13360 13360 i mdtimer:203 destroy timerimpl id:2
2023-06-12 14:10:23.481353 13360 13360 i mdtimer:344 stop id:2
2023-06-12 14:10:23.481360 13360 13360 i mdtimer:203 destroy timerimpl id:1
2023-06-12 14:10:23.481365 13360 13360 i mdtimer:344 stop id:1
2023-06-12 14:10:23.481371 13360 13360 i mdtimer:291 ~timermanager.
2023-06-12 14:10:23.481467 13360 13361 i mdtimer:256 timertickthread exit.
2023-06-12 14:10:23.481629 13360 13362 i mdtimer:285 timercallbackthread exit.
后续思考本定时器设计简洁高效,应用方便,满足绝大多数场景的使用;当需要创建或管理大量定时器时,由于定时器start时插入消息时间复杂度为o(log2n),但stop时直接删除消息时间复杂度为o(n),因此引入了辅助的map用于解决该问题,使时间复杂度变为log2n;也可以使用时间轮定时器来优化,但处理逻辑会比较复杂。
LTE-M提供面向未来的物联网
紫光展锐进入到了6nm EUV工艺;中兴天机Axon 11 5G配置曝光...
监管人员定位系统的组成、功能特点及应用
电路设计基础知识:数字电源的调制方式
隆基、通威、晶澳、晶科、东方日升……不能错过的光伏产业盛会
定时器设计实现
纳睿雷达上半年营收增长53%,致力于打造全球领先的雷达系统
F5G四大商业创新应用前景广阔
新型红外光助力提升农药的有效利用率
红米Note 6 Pro的真机照片曝光,这款手机的一大卖点应该是拍照
“中国制造”这个词语的含义已经到了重写的时候,手机只是一个开始
场效应管SI2301BDS
RS为树莓派扩充无线连接解决方案
小米终于超越OPPO重返全球第四,并疯狂追赶华为
MS2351完美替代AD8315 MS2351参数特性介绍
Siemens 计划收购 Sarokal ,使其公司业务扩张到IC行业
魅族mx6:最耐看的魅族手机,越看越好看!
创意灯饰:摘掉一颗灯
联想手机走不通干脆不走了,智能型VR产品MR头盔8月上市,售价惊喜!
计数器,计数器的工作原理是什么?