jeudi 8 octobre 2020

Use of Promise and Future to provide continous periodic notifications from one thread to another

I have two threads. One thread acts as a timer thread which at regular intervals of time needs to send a notification to another thread. I am planning to use C++ Promise and Future for this purpose instead of C++ condition variables.

I have the following constraints/conditions :-

  1. Would like to avoid locking on to mutex (hence decided not to use C++ std::condition_variable as for that, one has to use mutex)
  2. The timer (or notifying) thread need not send a notification to the consumer if it is not ready yet (i.e. still acting on the last notification)

I decided to use C++ Promise and Future and came up with this piece of code.

// promiseFutureAtomic.cpp

#include <atomic>
#include <condition_variable>
#include <iostream>
#include <thread>
#include <iostream>       // std::cout, std::endl
#include <thread>         // std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
#include <future>

std::promise<void> aPromisingFuture;
std::atomic<bool> readyForNotification{false};
std::atomic<bool> stop_consumer{false};

void waitingForWork(){
    while (!stop_consumer)
    {
        std::cout << "Waiting " << std::endl;
        
        std::promise<void> newPromise;
        aPromisingFuture = std::move(newPromise);
        auto aFuture = aPromisingFuture.get_future();
        readyForNotification = true;
        aFuture.wait();
        std::cout << "Running " << std::endl;
        // Do useful work but no critical section.
    }
}

void setDataReady(){
    int i = 0;
    while (i++ < 10)
    {
        std::this_thread::sleep_for (std::chrono::seconds(1));
        if (readyForNotification)
        {
            readyForNotification = false;
            std::cout << "Data prepared" << std::endl;
            aPromisingFuture.set_value();
        }
    }
    stop_consumer = true;
}

int main(){
    
  std::cout << std::endl;

  std::thread t1(waitingForWork);
  std::thread t2(setDataReady);

  t1.join();
  t2.join();
  
  std::cout << std::endl;
  
}

My question is :-

  1. How would the performance of this approach compare with that the upcoming C++20 std::atomic_wait/std::atomic_notify ?
  2. Does std::future<T>::wait() suffer from spurious wakeups (like C++ std::condition_variable::wait) ?
  3. Are there any drawbacks of this approach over a regular approach using std::condition_variable::wait ?

Aucun commentaire:

Enregistrer un commentaire