#ifndef L1_TIMER_H_
#define L1_TIMER_H_
#include <iostream>
#include <set>
#include <atomic>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include <functional>
#include <iomanip>
#include <shared_mutex>
#include <unordered_map>
using namespace std;
class L1Timer
{
public:
using Callback = std::function<void(unsigned int)>;
L1Timer(const std::string& name, Callback callback, unsigned int interval)
: name_(name), callback_(callback), interval_(interval), running_(false) {}
void start()
{
//std::lock_guard<std::mutex> lock(mutex_);
if (!running_)
{
running_ = true;
tp_ = std::chrono::steady_clock::now();// use other tp clock huimingf
tp_sys_ = std::chrono::system_clock::now();
}
}
void update(const std::string& name, Callback callback, unsigned int interval)
{
name_ = name;
callback_ = callback;
interval_ = interval;
}
void stop()
{
//std::lock_guard<std::mutex> lock(mutex_);
running_ = false;
}
void dump(stringstream &oss) const
{
std::stringstream ss;
time_t t1 = std::chrono::system_clock::to_time_t(tp_sys_);
ss << std::put_time(localtime(&t1), "%Y-%m-%d %H:%M:%S");
oss << "timer[" << name_ << "] start: " << ss.str() << " interval: " << interval_
<< " status:" << (running_ ? " running":" stopped") << std::endl;
}
const std::string& getName() const
{
return name_;
}
bool isRunning() const
{
return running_;
}
unsigned int getInterval() const
{
return interval_;
}
void executeCallback(unsigned int index) const
{
if (callback_)
{
callback_(index);
}
}
std::chrono::steady_clock::time_point getStartTime()
{
return tp_;
}
unsigned int getTimeCountDown()
{
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - tp_);
if (elapsed.count() < interval_)
{
return interval_ - elapsed.count();
}
else
{
return 0;
}
}
private:
std::string name_;
Callback callback_;
unsigned int interval_;
std::chrono::steady_clock::time_point tp_;
std::chrono::system_clock::time_point tp_sys_;//use for dump
//mutable std::mutex mutex_;
std::atomic<bool> running_;
};
class L1TimerManager
{
public:
L1TimerManager();
~L1TimerManager();
static shared_ptr<L1TimerManager> GetL1TimerManager();
void createTimer(const unsigned int &index, const std::string& name, L1Timer::Callback callback, unsigned int interval);
void updateTimer(const unsigned int &index, const std::string& name, L1Timer::Callback callback, unsigned int interval);
void registerDefaultCallback(L1Timer::Callback callback);
bool isTimerExisted(const unsigned int &index);
unsigned int getTimeCountDown(const unsigned int &index);
void startTimer(const unsigned int &index);
void stopTimer(const unsigned int &index);
void removeTimer(const unsigned int &index);
void dumpTimers(stringstream &oss);
void start();
void stop();
std::string timePoint2Str(std::chrono::system_clock::time_point tp_);
private:
void timerLoop();
private:
//std::vector<Timer> timers_;
//std::unordered_map<unsigned int, std::shared_ptr<L1Timer>> timers_;
static shared_ptr<L1TimerManager> instance_;
std::map<unsigned int, std::shared_ptr<L1Timer>> timers_;
std::shared_ptr<std::thread> timerThread_;
std::atomic<bool> running_;
mutable std::shared_mutex mutex_; // 用于同步对timers_的访问
L1Timer::Callback default_call_back;
};
#endif /* L1_TIMER_H_ */
#include <map>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <string>
#include "l1_timer.h"
using namespace std;
shared_ptr<L1TimerManager> L1TimerManager::instance_ = nullptr;
L1TimerManager::L1TimerManager(): running_(false)
{
}
L1TimerManager::~L1TimerManager()
{
stop();
}
shared_ptr<L1TimerManager> L1TimerManager::GetL1TimerManager()
{
if(nullptr==instance_){
//instance_ = new L1Util();
instance_ = make_shared<L1TimerManager>();
}
return instance_;
}
void L1TimerManager::registerDefaultCallback(L1Timer::Callback callback)
{
std::unique_lock<std::shared_mutex> lck(mutex_);
default_call_back = callback;
}
bool L1TimerManager::isTimerExisted(const unsigned int &index)
{
std::unique_lock<std::shared_mutex> lck(mutex_);
if (timers_.find(index) != timers_.end())
{
return true;
}
return false;
}
unsigned int L1TimerManager::getTimeCountDown(const unsigned int &index)
{
std::unique_lock<std::shared_mutex> lck(mutex_);
auto it = timers_.find(index);
if (it != timers_.end())
{
return it->second->getTimeCountDown();
}
else
{
return 0;
}
}
void L1TimerManager::createTimer(const unsigned int &index, const std::string& name, L1Timer::Callback callback, unsigned int interval)
{
std::unique_lock<std::shared_mutex> lck(mutex_);
L1Timer::Callback act_callback = default_call_back;
if (callback)
{
act_callback = callback;
}
else
{
//LOG("create Timer:" << index << " name " << name << " default call_back");
}
if (timers_.find(index) != timers_.end())
{
//LOG("create Timer:" << index << " name " << name << "failed");
}
else
{
timers_[index] = std::make_shared<L1Timer>(name, act_callback, interval);
//LOG("create Timer:" << index << " name " << name << " successfully");
}
}
void L1TimerManager::updateTimer(const unsigned int &index, const std::string& name, L1Timer::Callback callback, unsigned int interval)
{
std::unique_lock<std::shared_mutex> lck(mutex_);
L1Timer::Callback act_callback = default_call_back;
if (callback)
{
act_callback = callback;
}
else
{
//LOG("update Timer:" << index << " name " << name << " default call_back");
}
auto it = timers_.find(index);
if (it == timers_.end())
{
//LOG("update Timer " << index << "failed");
}
else
{
it->second->update(name, act_callback, interval);
//LOG("update Timer:" << index << " name " << it->second->getName() << " successfully");
}
}
void L1TimerManager::startTimer(const unsigned int &index)
{
std::shared_lock<std::shared_mutex> lck(mutex_);
auto it = timers_.find(index);
if (it == timers_.end())
{
//LOG("start Timer " << index << "failed");
}
else
{
it->second->start();
//LOG("start Timer:" << index << " name " << it->second->getName() << " successfully");
}
}
void L1TimerManager::stopTimer(const unsigned int &index)
{
std::shared_lock<std::shared_mutex> lck(mutex_);
auto it = timers_.find(index);
if (it == timers_.end())
{
//LOG("stop Timer " << index << " name " << it->second->getName() << "failed");
}
else
{
it->second->stop();
}
}
void L1TimerManager::removeTimer(const unsigned int &index)
{
std::unique_lock<std::shared_mutex> lck(mutex_);
auto it = timers_.find(index);
if (it == timers_.end())
{
//LOG("remove Timer " << index << " name " << it->second->getName() << "failed");
}
else
{
//stopTimer(name);
//LOG("remove Timer " << index << " name " << it->second->getName() << "successfully");
it->second->stop();
timers_.erase(it);
}
}
void L1TimerManager::dumpTimers(stringstream &oss)
{
std::shared_lock<std::shared_mutex> lck(mutex_);
for(auto& kv:timers_){
(kv.second)->dump(oss);
}
}
void L1TimerManager::start()
{
if (!running_)
{
running_ = true;
timerThread_ = make_shared<std::thread>(&L1TimerManager::timerLoop, this);
std::string name = "l1TestMon";
pthread_setname_np(timerThread_->native_handle(), name.c_str());
}
}
void L1TimerManager::stop()
{
if (running_)
{
running_ = false;
if (timerThread_)
{
timerThread_->join();
//SWSS_LOG_INFO("Thread: l1TestMon stopped!");
}
}
}
std::string L1TimerManager::timePoint2Str(std::chrono::system_clock::time_point tp_)
{
std::stringstream ss;
time_t t1 = std::chrono::system_clock::to_time_t(tp_);
ss << std::put_time(localtime(&t1), "%Y-%m-%d %H:%M:%S");
//std::cout << "time: " << ss.str() << std::endl;
return ss.str();
}
void L1TimerManager::timerLoop()
{
stringstream oss;
while (running_)
{
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Adjust sleep time as needed
oss.clear();
oss.str("");
std::shared_lock<std::shared_mutex> lck(mutex_);
for (auto&item : timers_)
{
unsigned int index = item.first;
std::shared_ptr<L1Timer> timer = item.second;
if (timer->isRunning())
{
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - timer->getStartTime());
if (elapsed.count() >= timer->getInterval())
{
//std::cout << "current time: " << timePoint2Str(now) << std::endl;
timer->executeCallback(index);
timer->dump(oss); // Optional: Print timer status
//LOG("dump:" << oss.str());
//timer.start(); // Restart the timer
timer->stop();
}
}
}
}
}
void TimerCallBackFunc(unsigned int lc_index)
{
std::cout << lc_index << " Timer ticked!!!" << std::endl;
return;
}
L1TimerManager tm1;
int main() {
std::stringstream oss;
tm1.createTimer(1, "myTimer1", TimerCallBackFunc, 3);
tm1.createTimer(2, "myTimer2", TimerCallBackFunc, 5);
tm1.createTimer(3, "myTimer3", TimerCallBackFunc, 7);
tm1.createTimer(4, "myTimer4", TimerCallBackFunc, 9);
tm1.createTimer(5, "myTimer5", TimerCallBackFunc, 11);
tm1.createTimer(6, "myTimer6", TimerCallBackFunc, 13);
tm1.start();
tm1.startTimer(1);
tm1.startTimer(2);
tm1.startTimer(3);
tm1.startTimer(4);
tm1.startTimer(5);
tm1.startTimer(6);
// Let the timers run for a while
std::this_thread::sleep_for(std::chrono::seconds(20));
tm1.dumpTimers(oss);
std::cout << "dump:" << oss.str() << std::endl;
tm1.stop();
std::cout << "-----remove Timer ----" << std::endl;
tm1.removeTimer(1);
tm1.removeTimer(2);
return 0;
}