yy1717
2022-12-08 f7a18ec4494b9c5c9ef3fd440bbf68ffc6425e18
lib/src/main/cpp/common/apptimer.cpp
@@ -1,188 +1,262 @@
//POSIX.1b Timer
#include <jni.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include "../jni_log.h"
//
// Created by YY on 2021/3/16.
//
#include "apptimer.h"
#include "../jni_log.h"
#define MAX_TIMER    32
#include <cstdint>
#include <functional>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <list>
#include <thread>
#include <map>
#include <string>
#include <sstream>
#include <iomanip>
static struct {
    timer_t timerId;
#define DEBUG(fmt, args...)     LOGD("<apptimer> <%s>: " fmt, __func__, ##args)
    void (*func)(union sigval sig);
std::mutex mtx;
    int value;
    uint8_t *user_data;
} AppTimer[MAX_TIMER];
std::map<void(*)(apptimer_var_t), CTimer *> TimerList;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static void RemoveTimerList(const CTimer *p);
static int createTimer(timer_t *timerId, void (*func)(union sigval sig),
                       int value,
                       uint8_t *usr_data, int usr_data_length,
                       uint8_t **usr_data_ptr) {
    struct sigevent sev;
    pthread_attr_t attr;
CTimer::CTimer() {
    flag = 0;
    var.var_ptr = nullptr;
    var.var1 = var.var2 = var.var_length = 0;
    pthread = nullptr;
}
    // Register printMsg to SIGALRM
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
CTimer::~CTimer() {
    if (pthread != nullptr) {
        delete pthread;
    }
    if (var.var_ptr != nullptr) {
        delete var.var_ptr;
    }
}
    memset(&sev, 0, sizeof(sev));
bool CTimer::_updateStatus(CTimer *timer) {
    if (timer->flag == 0) {
        return false;
    } else {
        return true;    //cancel
    }
}
    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = func;
    sev.sigev_notify_attributes = &attr;
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);
    if (usr_data != NULL && usr_data_length != 0) {
        if ((sev.sigev_value.sival_ptr = malloc(usr_data_length)) != NULL) {
            *usr_data_ptr = (uint8_t *) sev.sigev_value.sival_ptr;
            memcpy(sev.sigev_value.sival_ptr, usr_data, usr_data_length);            //Copy usr data
            sev.sigev_value.sival_int = usr_data_length;
        } else {
            return -1;
    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 {
        sev.sigev_value.sival_int = value;
//        LOGD("Cancel %d", static_cast<int>(timer->flag));
        RemoveTimerList(timer);
    }
    /* create timer */
    if (timer_create(CLOCK_REALTIME, &sev, timerId) == -1) {
        return -1;
    //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;
    }
//    LOGD("timer_create\n");
    return 0;
}
static int setTimer(timer_t timerId, int timeMSec) {
    struct itimerspec its;
    /* Start the timer */
    its.it_value.tv_sec = timeMSec / 1000;
    its.it_value.tv_nsec = (timeMSec % 1000) * 1000000;
    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 0;
    if (timer_settime(timerId, 0, &its, NULL) == -1) {
        return -1;
void CTimer::clear(CTimer *timer)
{
    if (timer != nullptr) {
        delete timer;
    }
//    LOGD("timer_settime\n");
    return 0;
}
void AppTimer_Init(void) {
    memset(AppTimer, 0, sizeof(AppTimer));
    pthread_mutex_init(&mutex, NULL);
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 AppTimer_add(void (*func)(union sigval), int timeMS) {
    int i;
//   LOGD("AppTimer_add\n");
    pthread_mutex_lock(&mutex);
    for (i = 0; i < MAX_TIMER; i++) {
        if (AppTimer[i].func == NULL) {
            if (createTimer(&(AppTimer[i].timerId), func, 0, NULL, 0, &(AppTimer[i].user_data)) == 0) {
                AppTimer[i].func = func;
void CTimer::stop() {
    std::unique_lock<std::mutex> lk(this->cv_mtx);
    this->flag = 1;
    this->cv.notify_one();
}
                if (setTimer(AppTimer[i].timerId, timeMS) !=
                    0) {            //Set timer fail, delele it
                    timer_delete(AppTimer[i].timerId);
                    if (AppTimer[i].user_data != NULL) {
                        free(AppTimer[i].user_data);
                        AppTimer[i].user_data = NULL;
                    }
                    AppTimer[i].func = NULL;
                }
            }
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;
        }
    }
    pthread_mutex_unlock(&mutex);
}
void AppTimer_add(void (*func)(union sigval), int timeMS, uint8_t *data, int length) {
    int i;
//   LOGD("AppTimer_add\n");
    pthread_mutex_lock(&mutex);
    for (i = 0; i < MAX_TIMER; i++) {
        if (AppTimer[i].func == NULL) {
            if (createTimer(&(AppTimer[i].timerId), func, 0, data, length, &(AppTimer[i].user_data)) == 0) {
                AppTimer[i].func = func;
                if (setTimer(AppTimer[i].timerId, timeMS) !=
                    0) {            //Set timer fail, delele it
                    timer_delete(AppTimer[i].timerId);
                    if (AppTimer[i].user_data != NULL) {
                        free(AppTimer[i].user_data);
                        AppTimer[i].user_data = NULL;
                    }
                    AppTimer[i].func = NULL;
                }
            }
            break;
        }
    }
    pthread_mutex_unlock(&mutex);
}
void AppTimer_add(void (*func)(union sigval), int timeMS, int value) {
    int i;
//   LOGD("AppTimer_add\n");
    pthread_mutex_lock(&mutex);
    for (i = 0; i < MAX_TIMER; i++) {
        if (AppTimer[i].func == NULL) {
            if (createTimer(&(AppTimer[i].timerId), func, value, NULL, 0, &(AppTimer[i].user_data)) == 0) {
                AppTimer[i].func = func;
                if (setTimer(AppTimer[i].timerId, timeMS) !=
                    0) {            //Set timer fail, delele it
                    timer_delete(AppTimer[i].timerId);
                    if (AppTimer[i].user_data != NULL) {
                        free(AppTimer[i].user_data);
                        AppTimer[i].user_data = NULL;
                    }
                    AppTimer[i].func = NULL;
                }
            }
            break;
        }
    }
    pthread_mutex_unlock(&mutex);
}
void AppTimer_delete(void (*func)(union sigval)) {
    int i;
//   LOGD("AppTimer_delete\n");
    pthread_mutex_lock(&mutex);
    for (i = 0; i < MAX_TIMER; i++) {
        if (AppTimer[i].func == func) {
            timer_delete(AppTimer[i].timerId);
            if (AppTimer[i].user_data != NULL) {
                free(AppTimer[i].user_data);
                AppTimer[i].user_data = NULL;
            }
            AppTimer[i].func = NULL;
        }
    }
    pthread_mutex_unlock(&mutex);
}
uint32_t AppTimer_GetTickCount(void)
{
    struct timespec ts;
    std::chrono::milliseconds as = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return as.count();
}
    return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
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;
}