lundi 23 septembre 2019

oneshot Timer callback used by C++11 std::async

I created it using std :: async in C ++ 11. Is there anything wrong with using it? I'd like to receive feedback on what I can improve or what's wrong.

I don't have any experience with C ++ 11, so I wonder if the use of async or smart pointer is wrong. Is there a problem without calling get () on async's return value std :: future?

Thank you!

HEADER (Timer.h)

#pragma once
#include <chrono>
#include <functional>
#include <map>
#include <future>

enum class TIMER_STATUS
{
    RUNNING,
    FINISHED,
    CANCELED,
};
struct TIMER_HANDLE_T
{
    friend class Timer;

public:
TIMER_HANDLE_T();
~TIMER_HANDLE_T();

private:
    std::chrono::microseconds afterMS;  
    std::function<void(void)> callback; 
    std::future<void> waiter;   
    std::promise<void> exitSignal;  //used by cancel    
    TIMER_STATUS status;
};
typedef std::shared_ptr<TIMER_HANDLE_T> TIMER_HANDLE;

class Timer
{

public:
    Timer();
    ~Timer();

    //Start
    TIMER_HANDLE Set(std::chrono::milliseconds ms, std::function<void(void)> callback);
    //Cancel
    bool Reset(TIMER_HANDLE h);
    TIMER_STATUS GetStatus(TIMER_HANDLE h);

private:
    void Wait(TIMER_HANDLE h, std::future<void> exitSig);
};

CPP (Timer.cpp)

#include "Timer.h"
#include <thread>

TIMER_HANDLE_T::TIMER_HANDLE_T(){   }
TIMER_HANDLE_T::~TIMER_HANDLE_T(){  }
Timer::Timer(){ }
Timer::~Timer(){    }

TIMER_HANDLE Timer::Set(std::chrono::milliseconds ms, std::function<void(void)> callback)
{
    std::shared_ptr<TIMER_HANDLE_T> th = std::make_shared<TIMER_HANDLE_T>();
    th->callback = callback;
    th->afterMS = ms;
    th->exitSignal = std::promise<void>();
    th->waiter = std::async(std::launch::async, &Timer::Wait, this, th, th->exitSignal.get_future());
    th->status = TIMER_STATUS::RUNNING;
    return std::move(th);
}
bool Timer::Reset(TIMER_HANDLE h)
{
    h->exitSignal.set_value();
    if (h->waiter.wait_for(std::chrono::milliseconds(1000)) == std::future_status::ready)
        return true;
    else
        return false;
}
TIMER_STATUS Timer::GetStatus(TIMER_HANDLE h)
{
    return h->status;
}

void Timer::Wait(TIMER_HANDLE h, std::future<void> exitSig)
{
    if (exitSig.wait_for(h->afterMS) == std::future_status::timeout)
    {
        h->callback();
        h->status = TIMER_STATUS::FINISHED;
    }
    else
    {
        h->status = TIMER_STATUS::CANCELED;
    }
}

USED (main.cpp)

#include "Timer.h"
#include <iostream>

std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

void Callback()
{
    std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
    std::cout << "Callback - " << sec.count() << std::endl;

    //Do Something
}

int main()
{
    Timer t;
    TIMER_HANDLE b = t.Set(std::chrono::milliseconds(5000), &Callback);

std::this_thread::sleep_for(std::chrono::milliseconds(10000));

    return 0;
}

The output is "Callback - 5.00091"

Aucun commentaire:

Enregistrer un commentaire