美文网首页
用c++11 实现异步定时回调

用c++11 实现异步定时回调

作者: 诸事圆成 | 来源:发表于2022-10-28 18:04 被阅读0次

1. 比较少代码的方案,测试正常 【std::async + std:condition_varibale + std::function】

但是有点不理解,多个线程同时调asyncWait,如果把asyncWait返回的std::future<void>全部赋值给同一个对象,是否会有线程安全问题 但是测试是正常的

#include <iostream>
#include <chrono>
#include <future>
#include <thread>
#include <mutex>
#include <condition_variable>

class GpDeadTimer
{
public:
    GpDeadTimer(){}
    ~GpDeadTimer(){}

    //异步超时回调, 一定要接返回值,不然不会异步
    std::future<void> asyncWait(int mesc, std::function<void()> callback_fun)
    {
        return std::async(std::launch::async, [this, mesc, callback_fun](){
            std::unique_lock<std::mutex> lck(timer_mtx_);
            stop_timer_ = false;
            if (!timer_cv_.wait_for(lck, std::chrono::milliseconds(mesc), [this]{ return stop_timer_ == true; }))
            {
                callback_fun();
            }
            else
            {
                std::cout << "operator break\n";
            }
        });
    }

    void cancel()
    {
        {
          std::lock_guard<std::mutex> lck(timer_mtx_);
          stop_timer_ = true;
        }
        timer_cv_.notify_all();
    }

private:
    std::mutex timer_mtx_;
    std::condition_variable timer_cv_;
    std::atomic<bool> stop_timer_{true};
};

测试:

image.png

2. 比较复杂可能很多地方写的多余了

#ifndef TIMER_H
#define TIMER_H

#include <iostream>
#include <chrono>
#include <atomic>
#include <thread>
#include <mutex>

//实现同步或异步定时器
enum class eDeadType
{
    eNoTimeout,          /*timeout <= 0*/
    eTimeout,              /*正常超时退出*/
    eOperator_break,  /*主动终止*/
};

typedef  void  (*CallBackFunc)(eDeadType &type, void* arg);

class DeadLineTimerImpl
{
public:
    DeadLineTimerImpl(){}
    ~DeadLineTimerImpl()
    {
        stop_timer.store(true);
        if (wait_thread_.joinable())
        {
            wait_thread_.join();
        }
    }
    DeadLineTimerImpl(const DeadLineTimerImpl&) = delete;
    DeadLineTimerImpl& operator=(const DeadLineTimerImpl&) = delete;


    //设置超时从当前时间起
    void expires_from_now(int mesc)
    {
        wait_timeout_.store(mesc);
    }

    //取消超时操作
    void setCancel()
    {
        stop_timer.store(true);
    }

    //同步等待
    void wait()
    {
        if (wait_timeout_.load() <=  0)
            return;

        stop_timer = false;
        auto deadtime  = std::chrono::steady_clock::now() + std::chrono::milliseconds(wait_timeout_.load());
        while(std::chrono::steady_clock::now() < deadtime && stop_timer.load() == false)
        {//wait
        }

        return;
    }

    //异步等待
    void async_wait(CallBackFunc timeout_func, void* arg)
    {
        mtx_.lock();
        func_callback_ = timeout_func;
        callback_host_ = arg;
        if (wait_timeout_.load() <=  0){
            eDeadType type = eDeadType::eNoTimeout;
            if (this->func_callback_ != nullptr)
                func_callback_(type, callback_host_);
            return;
        }
        mtx_.unlock();

        stop_timer.store( false);
        auto func = [this](){
            std::lock_guard<std::mutex> lock(mtx_);
            auto deadtime  = std::chrono::steady_clock::now() + std::chrono::milliseconds(wait_timeout_.load());
            while(std::chrono::steady_clock::now() < deadtime && stop_timer.load() == false)
            { //wait
            }

            if (stop_timer.load() == false)
            {
                eDeadType type = eDeadType::eTimeout;
                if (this->func_callback_ != nullptr){
                    func_callback_(type, callback_host_);
                }
                return;
            }
            eDeadType type = eDeadType::eOperator_break;
            if (this->func_callback_ != nullptr){
                func_callback_(type, callback_host_);
            }
        };

        wait_thread_ = std::thread(func);
        return;
    }

private:
    std::mutex mtx_;
    CallBackFunc func_callback_;
    void *callback_host_{nullptr};
    std::atomic<bool> stop_timer{true};
    std::atomic<int>  wait_timeout_{3000};
    std::thread wait_thread_;
};


#endif // TIMER_H


测试

#include "timer.h"

void timeout_handler(eDeadType &type, void *arg);
class test
{
public:
    test(){}

    void doOperator()
    {
        std::cout << "_____________start\n";

        timer.expires_from_now(3000);
        timer.async_wait(timeout_handler, this);
        std::cout << "____________________end\n";

        //主动打断
#if 1
        std::this_thread::sleep_for(std::chrono::seconds(1));
        timer.setCancel();
#endif
    }

    void timeout(eDeadType &type)
    {
        std::cout << "inter receive    " << static_cast<int>(type) << std::endl;
        switch (type) {
        case eDeadType::eTimeout:
            std::cout << "timeout success " << idx+3 << std::endl;
            break;
        case eDeadType::eNoTimeout:
            std::cout << "no timeout " << idx << std::endl;
            break;
        case eDeadType::eOperator_break:
            std::cout << "operator break success " << idx+4 << std::endl;
            break;
        }
    }

private:
    int idx = 20;
    DeadLineTimerImpl timer;
};

void timeout_handler(eDeadType &type, void *arg)
{
    std::cout << "call back:  type:    " <<  static_cast<int>(type) << std::endl;
    reinterpret_cast<test*>(arg)->timeout(type);
}


int main(int argc, char *argv[])
{    
    test aa;
    aa.doOperator();

    return 0;
}
image.png

相关文章

  • 用c++11 实现异步定时回调

    1. 比较少代码的方案,测试正常 【std::async + std:condition_varibale + s...

  • 异步的实现

    异步的三种实现方式: 回调函数事件Promise 回调函数 回调函数不一定是异步 但是异步一定是回调函数。 事件 ...

  • 07_Node.js Event

    一、回调函数 callback 1、回调函数 Node.js 异步编程的直接体现就是回调,异步编程依托于回调来实现...

  • nodeJS回调函数

    NodeJS异步编程的直接体现就是回调函数。 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。回调函...

  • Node.js 回调函数

    Node.js 异步编程的直接体现就是回调。 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。 回调...

  • Node.js - 回调函数

    Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。 回调函...

  • node.js回调函数

    Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。回调函数...

  • Node.js 回调函数

    回调函数 Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了...

  • 回调函数

    nodejs异步编程的体现就是回调异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。回调函数在完成任务...

  • node.js(六)

    Node.js 回调函数Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后...

网友评论

      本文标题:用c++11 实现异步定时回调

      本文链接:https://www.haomeiwen.com/subject/qefctdtx.html