龙空技术网

c++ 定时管理器

我要上班 58

前言:

现时朋友们对“c语言定时调用函数”大约比较注重,姐妹们都需要分析一些“c语言定时调用函数”的相关资讯。那么小编同时在网络上汇集了一些对于“c语言定时调用函数””的相关内容,希望姐妹们能喜欢,姐妹们快快来学习一下吧!

定时管理器

定时器是一种常用的组件, 一般的框架都提供,可惜c++标准库没有提供。

下面实现一个简单通用的定时管理器

#include <map>#include <mutex>#include <chrono>#include <memory>#include <thread>#include <functional>class TimerMgr {    struct TimerMgr::Timer;public:    TimerMgr(int maxThreads = 3, int intervalMilliseconds = 100)         : m_maxThreads(maxThreads), m_interval(intervalMilliseconds){}    ~TimerMgr() {        Stop();    }    void Stop() {        m_exit = true;        while (!m_threads.empty()) {            if (m_threads.begin()->second.joinable()) {                m_threads.begin()->second.join();            }            m_threads.erase(m_threads.begin());        }    }    //添加定时器, 返回定时器ID    int AddTimer(int milliseconds, std::weak_ptr<std::function<void()>> func, bool exclusive = false) {        std::shared_ptr<std::function<int(int)>> backFunc = std::make_shared<std::function<int(int)>>([func](int id)->int {            std::shared_ptr<std::function<void()>> upFunc(func.lock());            if (upFunc == nullptr) {                return -1;            }            upFunc->operator()();            return 0;        });        return AddTimer(milliseconds, exclusive, backFunc, backFunc);    }        //添加定时器, 返回定时器ID    int AddTimer(int milliseconds, std::weak_ptr<std::function<void(int)>> func, bool exclusive = false) {        std::shared_ptr<std::function<int(int)>> backFunc = std::make_shared<std::function<int(int)>>([func](int id)->int {            std::shared_ptr<std::function<void(int)>> upFunc(func.lock());            if (upFunc == nullptr) {                return -1;            }            upFunc->operator()(id);            return 0;         });        return AddTimer(milliseconds, exclusive, backFunc, backFunc);    }    //添加定时器, 返回定时器ID    int AddTimer(int milliseconds, std::weak_ptr<std::function<int(int)>> func, bool exclusive = false) {        return AddTimer(milliseconds, exclusive, func,  nullptr);    }    //删除定时器, 输入参数为定时器ID    void RemoveTimer(int timerId) {        std::lock_guard<std::mutex> lock(m_mutex);        auto iter = m_timers.find(timerId);        if (iter != m_timers.end()) {            iter->second.remove = true;        }    }private:    bool GetActive(struct TimerMgr::Timer*& timer) {        using namespace std::chrono;        std::lock_guard<std::mutex> lock(m_mutex);        int64_t now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();        for (auto iter = m_timers.begin(); iter != m_timers.end(); ) {            if (iter->second.remove && !iter->second.active) {                //清理已经失效的定时器                if (iter->second.exclusive && m_threads[iter->first].joinable()) {                    m_threads[iter->first].join();                    m_threads.erase(iter->first);                }                m_timers.erase(iter++);                continue;            }            if (iter->second.active || iter->second.exclusive || now < iter->second.activeTime) {                ++iter;                continue;            }            iter->second.active = true;            timer = &iter->second;            return true;        }        return false;    }        int AddTimer(int millisec, bool exclusive,        std::weak_ptr<std::function<int(int)>> cbFunc,          std::shared_ptr<std::function<int(int)>> backFunc = nullptr) {        using namespace std::chrono;        std::lock_guard<std::mutex> lock(m_mutex);        if (m_exit) {            return -1;        }        //寻找新的定时器ID        while (m_timers.end() != m_timers.find(m_maxTimerId)) {            m_maxTimerId = (m_maxTimerId > 0x3FFFFFFE) ? 1 : m_maxTimerId + 1;        }        //定时器间隔时间不能小于100毫秒        millisec = (millisec < 100) ? 100 : millisec;        struct Timer timer;        timer.id = m_maxTimerId++;        timer.exclusive = exclusive;        timer.millisec = millisec;        timer.activeTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() + millisec;        timer.cbFunc = cbFunc;        timer.backFunc = backFunc;        m_timers[timer.id] = timer;        if (!m_init) {            //没有初始化,则在这里初始化定时器线程            m_init = true;            for (int i = 1; i <= m_maxThreads; i++) {                m_threads[0 - i] = std::thread([this]() {                    struct Timer* timer = nullptr;                    do {                        if (!GetActive(timer)) {                            std::this_thread::sleep_for(milliseconds(m_interval));                            continue;                        }                        std::shared_ptr<std::function<int(int)>> func(timer->cbFunc.lock());                        timer->remove = (func == nullptr || 0 != func->operator()(timer->id));                        timer->activeTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() + timer->millisec;                        timer->active = false;                    } while (!m_exit);                });            }        }        if (exclusive) {            //排它性的定时器,单独创建一个线程处理            struct Timer& _timer = m_timers[timer.id];            m_threads[timer.id] = std::thread([this, &_timer]() {                _timer.active = true;                                bool over(false);                do {                    int64_t now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();                    if (now < _timer.activeTime) {                        std::this_thread::sleep_for(milliseconds((_timer.activeTime - now > 1000) ? 1000 : _timer.activeTime - now));                        continue;                    }                    std::shared_ptr<std::function<int(int)>> func(_timer.cbFunc.lock());                    over = (func == nullptr || 0 != func->operator()(_timer.id));                    _timer.activeTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() + _timer.millisec;                } while (!m_exit && !over);                _timer.active = false;                _timer.remove = true;            });        }        return timer.id;    }private:    int m_maxTimerId = 1;    int m_interval = 100;    int m_maxThreads = 3;    bool m_init = false;    bool m_exit = false;    std::mutex m_mutex;    std::map<int, struct TimerMgr::Timer> m_timers;    std::map<int, std::thread> m_threads;private:    struct Timer    {        int id = 0;        int millisec = 0;        bool exclusive = false;        bool active = false;        bool remove = false;        int64_t activeTime = 0;        std::weak_ptr<std::function<int(int)>> cbFunc = std::weak_ptr<std::function<int(int)>>();        std::shared_ptr<std::function<int(int)>> backFunc = nullptr;    };};

文心一言的解析如下:

这段代码是一个C++类的部分实现,这个类似乎被命名为TimerMgr。以下是对这段代码的详细解释:

私有成员变量:

* `m_maxTimerId`: 这是当前使用的最大定时器ID,初始化为1。* `m_interval`: 定时器的间隔时间,单位为毫秒,初始化为100毫秒。* `m_maxThreads`: 最大线程数,初始化为3。* `m_init`: 一个布尔值,表示是否已经初始化。初始化为false。* `m_exit`: 一个布尔值,表示是否应该退出。初始化为false。* `m_mutex`: 一个互斥锁,用于保护类的成员变量,防止多个线程同时访问它们。* `m_timers`: 一个映射,将定时器ID映射到`Timer`结构体实例。* `m_threads`: 一个映射,将线程ID映射到线程对象。
私有结构体 Timer:
* `id`: 定时器的唯一标识符。* `millisec`: 定时器的时间间隔,单位为毫秒。* `exclusive`: 一个布尔值,表示这个定时器是否是独占的。* `active`: 一个布尔值,表示定时器是否处于活动状态。* `remove`: 一个布尔值,表示是否应该移除这个定时器。* `activeTime`: 定时器的下次活动时间。* `cbFunc`: 一个弱引用到`std::function<int(int)>`,它是一个回调函数,当定时器激活时会被调用。* `backFunc`: 一个共享引用到`std::function<int(int)>`,它也是一个回调函数,但它的用途在这段代码中没有明确说明。

这段代码定义了三个重载的 AddTimer 函数,它们都是用来添加计时器的。每个函数都接受不同的参数,并返回一个整数(定时器ID)。

第一个 AddTimer 函数接受一个整数 milliseconds 和一个 std::weak_ptr<std::function<void()>> func,其中 func 是一个可以被调用的对象(例如函数指针、Lambda 表达式等)。该函数创建一个新的 std::shared_ptr<std::function<int(int)>> backFunc,这个新的函数在被调用时会尝试对 func 进行加锁,如果成功则调用 func,否则返回 -1。然后它调用另一个 AddTimer 函数,将 backFunc 作为回调函数和之前的参数一起传入。第二个 AddTimer 函数与第一个类似,但是它接受一个额外的参数 std::weak_ptr<std::function<void(int)>> func,这个函数接受一个整数参数。其他部分与第一个函数相同。第三个 AddTimer 函数也是创建一个新的回调函数 backFunc,但是它不接受任何参数。然后它调用另一个 AddTimer 函数,将 backFunc 作为回调函数和之前的参数一起传入。

最后,这三个函数都返回一个整数(定时器ID),可能是添加计时器的结果(例如成功或失败)。

示例:

int main() {        std::shared_ptr<std::function<void()>> cbFunc1 = std::make_shared<std::function<void()>>([]() {        std::cout << "timer_id : no case timer_id" << std::endl;        });    std::shared_ptr<std::function<void(int)>> cbFunc2 = std::make_shared<std::function<void(int)>>([](int id) {        std::cout << "timer_id : "<< id << std::endl;        });    std::shared_ptr<std::function<int(int)>> cbFunc3 = std::make_shared<std::function<int(int)>>([](int id) {        std::cout << "timer_id : " << id << std::endl;        return 0;        });    TimerMgr timerMgr;    int tId1 = timerMgr.AddTimer(500, cbFunc1);    int tId2 = timerMgr.AddTimer(500, cbFunc2);    int tId3 = timerMgr.AddTimer(500, cbFunc3, true);    std::this_thread::sleep_for(std::chrono::seconds(5));    return 0;}

标签: #c语言定时调用函数