C++定时器的实现之格式修订版
生活随笔
收集整理的這篇文章主要介紹了
C++定时器的实现之格式修订版
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
個人認為一個完備的定時器需要有如下功能:
在某一時間點執行某一任務
在某段時間后執行某一任務
重復執行某一任務N次,任務間隔時間T
那么如何實現定時器呢?下面是我自己實現的定時器邏輯,源碼鏈接最后會附上。
定時器中主要的數據結構
優先級任務隊列:隊列中存儲任務,每個任務會添加時間戳,最近的時間戳的任務會先出隊。
鎖和條件變量:當有任務需要執行時,用于通知正在等待的線程從任務隊列中取出任務執行。
線程池:各個任務會放在線程池中執行。
下面是相關代碼:
class TimerQueue {public: ?struct InternalS { ? ? ?std::chrono::time_point<std::chrono::high_resolution_clock> time_point_; ? ? ?std::function<void()> func_; ? ? ?bool operator<(const InternalS& b) const { return time_point_ > b.time_point_; } ?}; ?enum class RepeatedIdState { kInit = 0, kRunning = 1, kStop = 2 }; private: ?std::priority_queuequeue_; ?bool running_ = false; ?std::mutex mutex_; ?std::condition_variable cond_;wzq::ThreadPool thread_pool_;std::atomic<int> repeated_func_id_; ?wzq::ThreadSafeMap<int, RepeatedIdState> repeated_id_state_map_;};如何開啟定時器功能
打開內部的線程池功能,用于執行放入定時器中的任務,同時新開一個線程,循環等待任務到來后送入線程池中執行。
bool Run() { ? ?bool ret = thread_pool_.Start(); ? ?if (!ret) { ? ? ? ?return false; ? ?} ? ?std::thread([this]() { RunLocal(); }).detach(); ? ?return true;} void RunLocal() { ? ?while (running_) { ? ? ? ?std::unique_lock<std::mutex> lock(mutex_); ? ? ? ?if (queue_.empty()) { ? ? ? ? ? ?cond_.wait(lock); ? ? ? ? ? ?continue; ? ? ? ?} ? ? ? ?auto s = queue_.top(); ? ? ? ?auto diff = s.time_point_ - std::chrono::high_resolution_clock::now(); ? ? ? ?if (std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() > 0) { ? ? ? ? ? ?cond_.wait_for(lock, diff); ? ? ? ? ? ?continue; ? ? ? ?} else { ? ? ? ? ? ?queue_.pop(); ? ? ? ? ? ?lock.unlock(); ? ? ? ? ? ?thread_pool_.Run(std::move(s.func_)); ? ? ? ?} ? ?}}如何在某一時間點執行任務
根據時間戳構造InternalS,放入隊列中:
template <typename F, typename... Args> void AddFuncAtTimePoint(const std::chrono::time_point<std::chrono::high_resolution_clock>& time_point, F&& f, ? ? ? ? ? ? ? ? ? ? ? ?Args&&... args) { ? ?InternalS s; ? ?s.time_point_ = time_point; ? ?s.func_ = std::bind(std::forward(f), std::forward(args)...); ? ?std::unique_lock<std::mutex> lock(mutex_); ? ?queue_.push(s); ? ?cond_.notify_all();}如何循環執行任務
首先為這個循環任務生成標識ID,外部可以通過ID來取消此任務繼續執行,代碼如下,內部以類似遞歸的方式循環執行任務。
template <typename R, typename P, typename F, typename... Args>int AddRepeatedFunc(int repeat_num, const std::chrono::duration& time, F&& f, Args&&... args) { ? ?int id = GetNextRepeatedFuncId(); ? ?repeated_id_state_map_.Emplace(id, RepeatedIdState::kRunning); ? ?auto tem_func = std::bind(std::forward(f), std::forward(args)...); ? ?AddRepeatedFuncLocal(repeat_num - 1, time, id, std::move(tem_func)); ? ?return id;} int GetNextRepeatedFuncId() { return repeated_func_id_++; } template <typename R, typename P, typename F>void AddRepeatedFuncLocal(int repeat_num, const std::chrono::duration& time, int id, F&& f) { ? ?if (!this->repeated_id_state_map_.IsKeyExist(id)) { ? ? ? ?return; ? ?} ? ?InternalS s; ? ?s.time_point_ = std::chrono::high_resolution_clock::now() + time; ? ?auto tem_func = std::move(f); ? ?s.repeated_id = id; ? ?s.func_ = [this, &tem_func, repeat_num, time, id]() { ? ? ? ?tem_func(); ? ? ? ?if (!this->repeated_id_state_map_.IsKeyExist(id) || repeat_num == 0) { ? ? ? ? ? ?return; ? ? ? ?} ? ? ? ?AddRepeatedFuncLocal(repeat_num - 1, time, id, std::move(tem_func)); ? ?}; ? ?std::unique_lock<std::mutex> lock(mutex_); ? ?queue_.push(s); ? ?lock.unlock(); ? ?cond_.notify_all();}聲明:
本文于網絡整理,版權歸原作者所有,如來源信息有誤或侵犯權益,請聯系我們刪除或授權事宜。
總結
以上是生活随笔為你收集整理的C++定时器的实现之格式修订版的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在 iPhone 上管理跟踪权限无法
- 下一篇: 苹果 iPhone 15 Pro Max