#ifndef TIMER_HPP_
#define TIMER_HPP_
#include <memory>
#include <queue>
#include <thread>
#include <functional>
#include <string>
#include <unordered_map>
#include <mutex>
#include <condition_variable>
#include "rclcpp/rclcpp.hpp"
#define WORK_MODE 1
#define WORK_PLAN ((WORK_MODE << 2) + 1)
#define CLEAR_PLAN ((WORK_MODE << 2) + 2)
using callbackPtr = std::function<void()>;
struct MinHeapNode
{
std::string time;
callbackPtr function;
int id;
MinHeapNode() : time(""), function(nullptr), id(0) {};
MinHeapNode(const std::string &time,const callbackPtr &f,const int &id)
: time(time), function(f), id(id) {};
bool operator<(const MinHeapNode &n) const {
return time > n.time;
}
bool comp(const MinHeapNode& a, const MinHeapNode &b) {
return a.time > b.time;
}
bool operator==(const MinHeapNode &n) const
{
if(id == n.id && time == n.time)
return true;
else
return false;
}
};
class MinHeap : public std::priority_queue<MinHeapNode>
{
public:
bool addnode(MinHeapNode node);
bool rmvnode(MinHeapNode node);
void clear();
};
class TIME
{
public:
TIME();
~TIME();
void addTimer(std::string time, callbackPtr callbackfunctino, int id);
void rmvTimer(std::string time, int id);
void start();
void stop();
void run_tick();
void run_callback();
static std::shared_ptr<TIME> getInstance(void);
private:
std::shared_ptr<MinHeap> _minheap;
std::shared_ptr<std::deque<callbackPtr>> _callback;
std::thread *_tickThread;
std::thread *_callbackThread;
std::mutex _tick_mutex;
std::mutex _callback_mutex;
std::condition_variable _cv;
};
#endif
#include "timer.hpp"
#include <algorithm>
#include <cstring>
#include <string>
bool MinHeap::addnode(MinHeapNode node)
{
push(node);
return true;
}
bool MinHeap::rmvnode(MinHeapNode node)
{
auto it = std::find(this->c.begin(), this->c.end(), node);
if (it == this->c.end()) {
return false;
}
if (it == this->c.begin()) {
this->pop();
} else {
this->c.erase(it);
std::make_heap(this->c.begin(), this->c.end(), this->comp);
}
return true;
}
void MinHeap::clear()
{
while(!this->empty()) {
this->pop();
}
}
TIME::TIME()
{
_minheap = std::make_shared<MinHeap>();
_callback = std::make_shared<std::deque<callbackPtr>>();
_tickThread = nullptr;
_callbackThread = nullptr;
}
TIME::~TIME()
{
if (_tickThread) {
if (_tickThread->joinable())
_tickThread->join();
delete _tickThread;
_tickThread = nullptr;
}
if (_callbackThread) {
if (_callbackThread->joinable())
_callbackThread->join();
delete _callbackThread;
_callbackThread = nullptr;
}
}
void TIME::addTimer(std::string time, callbackPtr callbackfunctino, int id)
{
MinHeapNode node(time, callbackfunctino, id);
std::unique_lock<std::mutex> mut(_tick_mutex);
_minheap->addnode(node);
RCLCPP_INFO(rclcpp::get_logger("time"), "ADD TIMER %s %d!", time.c_str(), id);
}
void TIME::rmvTimer(std::string time, int id)
{
MinHeapNode node(time, nullptr, id);
std::unique_lock<std::mutex> mut(_tick_mutex);
_minheap->rmvnode(node);
RCLCPP_INFO(rclcpp::get_logger("time"), "RMV TIMER %s %d!", time.c_str(), id);
}
void TIME::start()
{
RCLCPP_INFO(rclcpp::get_logger("time"), "TIMER START");
_tickThread = new std::thread(std::bind(&TIME::run_tick, this));
_callbackThread = new std::thread(std::bind(&TIME::run_callback, this));
_tickThread->detach();
_callbackThread->detach();
}
void TIME::stop()
{
RCLCPP_INFO(rclcpp::get_logger("time"), "TIMER STOP");
_minheap->clear();
_callback->clear();
if (_tickThread->joinable())
_tickThread->join();
if (_callbackThread->joinable())
_callbackThread->join();
delete _tickThread;
delete _callbackThread;
_tickThread = nullptr;
_callbackThread = nullptr;
}
std::shared_ptr<TIME> TIME::getInstance(void)
{
static std::shared_ptr<TIME> instance = nullptr;
if (!instance) {
instance = std::make_shared<TIME>();
}
return instance;
}
int cmpdate(std::string date)
{
time_t now = time(nullptr);
struct tm timeinfo;
if (!strptime(date.c_str(), "%Y.%m.%d %H:%M:%S", &timeinfo)) {
RCLCPP_ERROR(rclcpp::get_logger("time"), "FORMAT ERROR!");
}
time_t timeStamp = mktime(&timeinfo);
std::cout << date << " " <<timeStamp << "-" << now << "=" << timeStamp - now << std::endl;
return timeStamp - now;
}
void TIME::run_tick()
{
RCLCPP_INFO(rclcpp::get_logger("time"), "RUN TICK");
while (true)
{
std::cout<< "tick!" << std::endl;
std::unique_lock<std::mutex> mut(_tick_mutex);
if (_minheap->empty()) {
return;
}
MinHeapNode node = _minheap->top();
int cmptime = cmpdate(node.time);
if (cmptime > 0) {
RCLCPP_INFO(rclcpp::get_logger("time"), "steal wait!");
} else if (cmptime >= -60) {
RCLCPP_INFO(rclcpp::get_logger("time"), "time out!");
_minheap->pop();
std::unique_lock<std::mutex> fmut(_callback_mutex);
_callback->push_back(node.function);
_cv.notify_one();
fmut.unlock();
} else {
_minheap->pop();
RCLCPP_ERROR(rclcpp::get_logger("time"), "run time low than now time!");
}
mut.unlock();
std::this_thread::sleep_for(std::chrono::seconds(30));
}
}
void TIME::run_callback()
{
RCLCPP_INFO(rclcpp::get_logger("time"), "RUN CALLBACK");
while (true)
{
std::unique_lock<std::mutex> mut(_callback_mutex);
_cv.wait(mut, [this]() {return !_callback->empty();});
callbackPtr cp = _callback->front();
if (!cp) {
RCLCPP_ERROR(rclcpp::get_logger("time"), "callback function is empty!");
return;
}
_callback->pop_front();
cp();
RCLCPP_INFO(rclcpp::get_logger("time"), "exec!");
mut.unlock();
std::this_thread::yield();
}
}
int main(){
std::shared_ptr<TIME> timerMgr = TIME::getInstance();
timerMgr->addTimer(next.starttime, std::bind(&Schedule::start_action, this), WORK_PLAN);
timerMgr->addTimer(next.endtime, std::bind(&Schedule::stop_action, this), WORK_PLAN);
timerMgr->start();
for (auto s : schedule_list_) {
timerMgr->rmvTimer(s, WORK_PLAN);
}
}
根据执行时间插入定时器中,定时器维护两个线程,一个线程判断超时时间,一个线程执行回调函数。
定时器插入删除根据最小堆,时间前的任务插入到前面,删除根据时间和定时器类型定点删除。
定时器支持同一时刻多类型任务插入。

935

被折叠的 条评论
为什么被折叠?



