//
|
// Created by YY on 2021/3/16.
|
//
|
|
#include "apptimer.h"
|
#include "../jni_log.h"
|
|
#include <cstdint>
|
#include <functional>
|
#include <chrono>
|
#include <mutex>
|
#include <condition_variable>
|
#include <list>
|
#include <thread>
|
#include <map>
|
#include <string>
|
#include <sstream>
|
#include <iomanip>
|
|
#define DEBUG(fmt, args...) LOGD("<apptimer> <%s>: " fmt, __func__, ##args)
|
|
std::mutex mtx;
|
|
std::map<void(*)(apptimer_var_t), CTimer *> TimerList;
|
|
static void RemoveTimerList(const CTimer *p);
|
|
CTimer::CTimer() {
|
flag = 0;
|
var.var_ptr = nullptr;
|
var.var1 = var.var2 = var.var_length = 0;
|
pthread = nullptr;
|
}
|
|
CTimer::~CTimer() {
|
if (pthread != nullptr) {
|
delete pthread;
|
}
|
if (var.var_ptr != nullptr) {
|
delete var.var_ptr;
|
}
|
}
|
|
bool CTimer::_updateStatus(CTimer *timer) {
|
if (timer->flag == 0) {
|
return false;
|
} else {
|
return true; //cancel
|
}
|
}
|
|
void CTimer::_do_task_func(uint32_t msec, CTimer *timer, std::function<void(apptimer_var_t)> callback) {
|
std::unique_lock<std::mutex> lk(timer->cv_mtx);
|
|
auto now = std::chrono::steady_clock::now();
|
|
if (timer->cv.wait_until(lk, now + std::chrono::milliseconds(msec), std::bind(_updateStatus, timer)) == false) {
|
RemoveTimerList(timer); // 从列表中删除索引
|
|
if (timer->flag == 0) {
|
callback(timer->var);
|
}
|
} else {
|
// LOGD("Cancel %d", static_cast<int>(timer->flag));
|
RemoveTimerList(timer);
|
}
|
|
//delete timer;
|
lk.unlock();
|
std::thread(clear, timer).detach();
|
}
|
|
void CTimer::copy(int value1, int value2, const void *data, int length)
|
{
|
this->var.var1 = value1;
|
this->var.var2 = value2;
|
this->var.var_length = length;
|
if (length > 0 && data != nullptr) {
|
this->var.var_ptr = new uint8_t[length];
|
memcpy(this->var.var_ptr, data, length);
|
} else {
|
this->var.var_ptr = nullptr;
|
}
|
}
|
|
void CTimer::clear(CTimer *timer)
|
{
|
if (timer != nullptr) {
|
delete timer;
|
}
|
}
|
|
bool CTimer::start(uint32_t msec, std::function<void(apptimer_var_t)> callback) {
|
if (pthread == nullptr) {
|
try {
|
pthread = new std::thread(_do_task_func, msec, this, callback);
|
pthread->detach();
|
} catch (std::exception &ex) {
|
DEBUG("%s", ex.what());
|
return false;
|
}
|
// this->callbackThread = std::thread(_do_task_func, msec, this, callback);
|
// this->callbackThread.detach();
|
}
|
return true;
|
}
|
|
void CTimer::stop() {
|
std::unique_lock<std::mutex> lk(this->cv_mtx);
|
this->flag = 1;
|
this->cv.notify_one();
|
}
|
|
void AppTimer_init(void)
|
{
|
TimerList.clear();
|
}
|
|
void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec)
|
{
|
CTimer *cTimer = new CTimer();
|
cTimer->copy(0, 0, nullptr, 0);
|
|
std::lock_guard<std::mutex> lock(mtx);
|
TimerList.insert(std::pair<void (*)(apptimer_var_t), CTimer *>(cb, cTimer));
|
|
if (cTimer->start(msec, cb) == false) {
|
auto it = TimerList.find(cb);
|
if (it != TimerList.end()) {
|
CTimer *ptr = it->second;
|
TimerList.erase(it);
|
}
|
delete cTimer;
|
}
|
}
|
|
void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec, int value1, int value2)
|
{
|
CTimer *cTimer = new CTimer();
|
cTimer->copy(value1, value2, nullptr, 0);
|
|
std::lock_guard<std::mutex> lock(mtx);
|
TimerList.insert(std::pair<void (*)(apptimer_var_t), CTimer *>(cb, cTimer));
|
|
if (cTimer->start(msec, cb) == false) {
|
LOGD("建立失败");
|
auto it = TimerList.find(cb);
|
if (it != TimerList.end()) {
|
CTimer *ptr = it->second;
|
TimerList.erase(it);
|
}
|
delete cTimer;
|
}
|
}
|
|
void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec, void *data, int lenght)
|
{
|
CTimer *cTimer = new CTimer();
|
cTimer->copy(0, 0, data, lenght);
|
|
std::lock_guard<std::mutex> lock(mtx);
|
TimerList.insert(std::pair<void (*)(apptimer_var_t), CTimer *>(cb, cTimer));
|
|
if (cTimer->start(msec, cb) == false) {
|
auto it = TimerList.find(cb);
|
if (it != TimerList.end()) {
|
CTimer *ptr = it->second;
|
TimerList.erase(it);
|
}
|
delete cTimer;
|
}
|
}
|
|
void AppTimer_delete(void(*cb)(apptimer_var_t))
|
{
|
std::lock_guard<std::mutex> lock(mtx);
|
|
auto it = TimerList.find(cb);
|
if (it != TimerList.end()) {
|
CTimer *ptr = it->second;
|
TimerList.erase(it);
|
ptr->stop();
|
}
|
}
|
|
static void RemoveTimerList(const CTimer *p)
|
{
|
std::lock_guard<std::mutex> lock(mtx);
|
|
for (auto it = TimerList.begin(); it != TimerList.end(); ++it) {
|
CTimer *ptr = it->second;
|
if (ptr == p) {
|
TimerList.erase(it);
|
break;
|
}
|
}
|
}
|
|
uint32_t AppTimer_GetTickCount(void)
|
{
|
std::chrono::milliseconds as = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
|
return as.count();
|
}
|
|
uint32_t AppTimer_GetGmtTickCount(void)
|
{
|
std::chrono::seconds as = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch());
|
|
return as.count();
|
}
|
|
std::string FormatTime(const char *fmt)
|
{
|
auto now = std::chrono::system_clock::now();
|
auto timet = std::chrono::system_clock::to_time_t(now);
|
auto localTime = *std::localtime(&timet);
|
|
std::stringstream ss;
|
std::string str;
|
ss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S");
|
str = ss.str();
|
return str;
|
}
|
|
std::time_t MktimeString(const char *str, const char *fmt)
|
{
|
struct std::tm dt;
|
std::istringstream ss(str);
|
|
ss >> std::get_time(&dt, fmt);
|
|
std::stringstream out;
|
out << std::put_time(&dt, "%Y-%m-%d %H:%M:%S");
|
// DEBUG("%s, %ld", out.str().c_str(), std::mktime(&dt));
|
|
time_t utc = std::mktime(&dt);
|
|
return utc;
|
}
|
|
time_t TimeStamp(int year, int mon, int day, int hour, int min, int sec)
|
{
|
// YYHHDDhhmmss(GMT+8)
|
struct tm test_tm;
|
|
struct timeval tv;
|
struct timezone tz;
|
|
gettimeofday(&tv,&tz);
|
|
memset(&test_tm, 0, sizeof(test_tm));
|
|
test_tm.tm_year = year - 1900;
|
test_tm.tm_mon = mon - 1;
|
test_tm.tm_mday = day;
|
test_tm.tm_hour = hour;
|
test_tm.tm_min = min;
|
test_tm.tm_sec = sec;
|
|
return mktime(&test_tm) - tz.tz_minuteswest*60;
|
}
|