jeudi 14 février 2019

Improving the implementation of the timer(timeout event) in C++

My case looks like this: The program uses two threads, let's call them "Sender" and "Recipient" because it is a mechanism of interprocess communication.

The "Sender" thread after sending the message stops at the condition provided by std::condition_variable and the .wait (Lock) function. The "Recipient" thread informs the waiting thread about the response to his message using .notify_one().

I'm happy with the way it works, but I want to add the ability to handle the timeout.

I prepared the following class (I would like it to be universal so the notification function is defined from the external class) but I'm sure that it can be implemented better. I wanted to avoid a lot of CPU usage, that's why I used std::this_thread::sleep_for, but I suppose that it can be somehow replaced with std::this_thread::yield(). I would like to use eg std::future_status, but I do not know how to do it. How can this be improved? I can use std c++11 or boost 1.55.

class Timer
{
    private:
    int MsLimit;
    std::atomic<bool> Stop;
    std::atomic<bool> LimitReached;
    std::thread T;
    std::mutex M;
    std::function<void()> NotifyWaitingThreadFunction;

    void Timeout()
    {
        std::unique_lock<std::mutex> Lock(M);
        std::chrono::system_clock::time_point TimerStart = std::chrono::system_clock::now();
        std::chrono::duration<long long, std::milli> ElapsedTime;
        unsigned int T = 0;
        do
        {   std::this_thread::sleep_for(std::chrono::milliseconds(5));
            TimerEnd = std::chrono::system_clock::now();
            ElapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(TimerEnd - TimerStart);
            T+=ElapsedTime.count();
            if((T > MsLimit) && (!Stop))
            {   LimitReached = true;
                Stop = true;
            }
        }while(!Stop)

        if(LmitReached)
        {
            NotifyWaitingThreadFunction();
        }
    }

    public:
    Timer(int Milliseconds) : MsLimit(Milliseconds)
    {

    }
    void StartTimer()
    {
        Stop = false;
        LmitReached = false;
        Timer = std::thread(&Timer::Timeout,this);
    }
    void StopTimer()
    {
        std::unique_lock<std::mutex> Lock(M);
        Stop = true;
        LimitReached = false;
    }
    template<class T>
    void AssignFunction(T* ObjectInstance, void (T::*MemberFunction)())
    {
        NotifyWaitingThreadFunction = std::bind(MemberFunction,ObjectInstance);
    }
};

Aucun commentaire:

Enregistrer un commentaire