From ca23184273aaf13b3689abc50e0159cd2ec107e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=BB=E9=AD=82=E5=9C=A3=E4=BD=BF?= Date: Tue, 23 Jan 2024 16:27:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=AE=80=E5=8D=95=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 12 +++++- include/Timer.h | 94 ++++++++++++++++++++++++++++++++++++++++ main.cpp | 18 +++++++- src/Timer.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 include/Timer.h create mode 100644 src/Timer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 41689fe..677274c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,17 @@ cmake_minimum_required(VERSION 3.27) project(Timer) set(CMAKE_CXX_STANDARD 17) +include_directories(include) -add_executable(Timer +add_library(Timer + src/Timer.cpp + include/Timer.h +) + +add_executable(TimerLink main.cpp ) + +target_link_libraries(TimerLink + Timer +) diff --git a/include/Timer.h b/include/Timer.h new file mode 100644 index 0000000..a55005c --- /dev/null +++ b/include/Timer.h @@ -0,0 +1,94 @@ +// +// Created by ling on 24-1-23. +// + +#ifndef TIMER_TIMER_H +#define TIMER_TIMER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ling { + + /// 低精度定时器,最大时间粒度为秒 + class Timer { + private: + struct Task { + std::time_t time; + int64_t interval; + std::function fun; + int64_t id; + + void operator()(); + }; + + //执行函数,可以用来结合线程池使用 + static std::function fun)> call; + static int64_t nextId; + static std::mutex mutex; + static std::list list; + static std::thread thread; + static std::atomic flag; + static std::condition_variable listCV; + + std::function recall; + int64_t id = 0; + Task task; + + protected: + + static void addTask(const Task &task); + + public: + + template + explicit Timer(F &&f, Args &&...args) { + this->id = nextId++; + std::function func = std::bind(std::forward(f), std::forward( + args)...); // 连接函数和参数定义,特殊函数类型,避免左右值错误 + auto task_ptr = std::make_shared>(func); + std::function warpper_func = [task_ptr, this]() { + (*task_ptr)(); + this->recall(); + }; + this->recall = [this, func]() { + auto task_ptr = std::make_shared>(func); + std::function warpper_func = [task_ptr, this]() { + (*task_ptr)(); + this->recall(); + }; + this->task.time = std::time(nullptr) + this->task.interval; + this->task.fun = warpper_func; + addTask(task); + }; + task.fun = warpper_func; + task.id = this->id; + } + + + /// 启动定时器 + void start(int64_t interval); + + /// 重新启动定时器 + void start(); + + void stop() const; + + /// 设置任务执行器 + static void setCall(const std::function)> &call); + + /// 立即停止定时器,没有执行的任务将全部丢弃 + static void stopAll(); + + virtual ~Timer(); + }; + +} // ling + +#endif //TIMER_TIMER_H diff --git a/main.cpp b/main.cpp index bc8f460..77eaf04 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,22 @@ #include +#include int main() { - std::cout << "Hello, World!" << std::endl; + { + ling::Timer timer([]() { + std::cout << "Hello World!" << std::endl; + }); + timer.start(5); + getchar(); + std::cout << "停止" << std::endl; + timer.stop(); + getchar(); + std::cout << "重新启动" << std::endl; + timer.start(); + getchar(); + } + std::cout << "释放" << std::endl; + getchar(); + ling::Timer::stopAll(); return 0; } diff --git a/src/Timer.cpp b/src/Timer.cpp new file mode 100644 index 0000000..d7dfa5c --- /dev/null +++ b/src/Timer.cpp @@ -0,0 +1,112 @@ +// +// Created by ling on 24-1-23. +// + +#include "Timer.h" +#include +#include + +namespace ling { + + std::function fun)> Timer::call = [](const std::function &fun) { + std::thread thread1([fun]() { + fun(); + }); + thread1.detach(); + }; + int64_t Timer::nextId = 1; + std::mutex Timer::mutex; + std::list Timer::list; + std::condition_variable Timer::listCV; + std::atomic Timer::flag{true}; + std::thread Timer::thread([]() { + while (flag.load()) { + { + std::unique_lock lock(mutex); + // 如果任务列表为空,阻塞当前线程 + if (list.empty()) { + listCV.wait(lock); + } + if (list.empty()) + continue; + Task task = list.front(); + std::time_t time = std::time(nullptr); + if (task.time <= time) { + call(task.fun); + list.pop_front(); + continue; + } + } + sleep(1); + } + }); + + void Timer::Task::operator()() { + + } + + void Timer::setCall(const std::function)> &fun) { + ling::Timer::call = fun; + } + + void Timer::addTask(const Timer::Task &task) { + { + std::unique_lock lock(mutex); + // 后添加的定时任务触发时间一般都比先添加的任务晚,所以从后向前遍历列表,节省一些时间 + for (auto it = list.rbegin(); it != list.rend(); ++it) { + if (it->time > task.time) { + list.insert(it.base(), task); + goto back; + } + } + list.push_back(task); + } + back: + listCV.notify_one(); + } + + void Timer::stopAll() { + { + std::unique_lock lock(mutex); + flag.store(false); + list.clear(); + listCV.notify_all(); + } + thread.join(); + } + + void Timer::start(int64_t interval) { + { + std::unique_lock lock(mutex); + for (auto it = list.begin(); it != list.end(); ++it) { + if (it->id == this->id) { + list.erase(it); + break; + } + } + } + + this->task.time = std::time(nullptr) + interval; + this->task.interval = interval; + addTask(task); + } + + void Timer::stop() const { + std::unique_lock lock(mutex); + for (auto it = list.begin(); it != list.end(); ++it) { + if (it->id == this->id) { + list.erase(it); + break; + } + } + } + + void Timer::start() { + start(this->task.interval); + } + + Timer::~Timer() { + stop(); + } + +} // ling \ No newline at end of file