Usage of condition variable and create a simple reusable class - c++

I have created a class using condition variable where I can create an object and use it instead of writing the implementation of the condition variable.
Below is my code. Now the functionality works as expected.
I see some issues if I run valgrind.
So I have two requests.
Please check the class implementation of the class and confirm if there can be any issues.
There is a "still reachable" error in valgrind if I run a gtest with this code. I checked online and found that "still reachable" issue can be ignored and moreover this problem is shown even if I do not add any code inside the test case (empty test case). So I am not too much worried about this error.
here is my code.
//ConditionalVariable.h
#ifndef SOURCE_MBUTILS_CONDITIONALVARIABLE_H_
#define SOURCE_MBUTILS_CONDITIONALVARIABLE_H_
#include <mutex>
#include <condition_variable>
#include <chrono>
class ConditionalVariable {
public:
ConditionalVariable();
virtual ~ConditionalVariable();
/**
* wait for the condition to reset from thread 1
*/
void waitForCondition();
/**
* wait for the condition to reset from thread 1 for timeout (msec)
* returns false if timeout, true otherwise
*/
bool waitForCondtion(std::uint32_t timeout);
/**
* reset the condition from thread 1, normally after the wait is over!
*/
void resetCondition();
/**
* set the condition from thread 2
*/
void setTheCondition();
/**
* get current condition state
*/
bool isConditionNowSet();
private:
std::mutex _mtx;
std::condition_variable _cv;
bool _condition;
};
#endif /* SOURCE_MBUTILS_CONDITIONALVARIABLE_H_ */
//ConditionalVariable.cpp
#include "ConditionalVariable.h"
ConditionalVariable::ConditionalVariable(): _condition(false)
{
// TODO Auto-generated constructor stub
}
ConditionalVariable::~ConditionalVariable() {
// TODO Auto-generated destructor stub
}
void ConditionalVariable::waitForCondition()
{
std::unique_lock<std::mutex> lock(_mtx);
_cv.wait(lock, [this]{ return _condition;});
}
bool ConditionalVariable::waitForCondtion(std::uint32_t timeout)
{
auto timePoint = std::chrono::system_clock::now() + (std::chrono::milliseconds) timeout;
std::unique_lock<std::mutex> lock(_mtx);
return _cv.wait_until(lock, timePoint, [this]{return _condition;});
}
void ConditionalVariable::resetCondition() {
//make the condition false to reset!
std::lock_guard<std::mutex> lock(_mtx);
_condition = false;
}
void ConditionalVariable::setTheCondition()
{
std::lock_guard<std::mutex> lock(_mtx);
_condition = true;
_cv.notify_one();
}
bool ConditionalVariable::isConditionNowSet()
{
return _condition;
}
Below error is from valgrind

Related

Multi-consumer condition variable wait in the same instance's member function

I'm having trouble thinking of a way to properly implement a signalling mechanism for multiple listeners waiting in the same function for a producer to signal some new data continuously, without getting "signalled" for the same previous data-
I want all listeners to always see the latest available data (not caring about missed signals if they are busy), without repeats.
My attempt so far:
#include <functional>
#include <shared_mutex>
#include <condition_variable>
#include <thread>
class Signaller {
public:
// Used by producer, will hold on to the mutex uniquely as it modifies data
void Signal(const std::function<void()>& fnIn) {
std::unique_lock lock(m_mtx);
fnIn();
m_newData = true;
m_cv.notify_all();
}
// Used by consumers, will only hold shared mutex to read data
void Wait(const std::function<void()>& fnIn) {
{
std::shared_lock lock(m_mtx);
m_cv.wait(lock, [this](){ return m_newData; });
fnIn();
}
// Need some way to flip m_newData to false when all threads are "done"
// (or some other method of preventing spurious wakeups)
// I don't think this is particularly ideal
{
std::unique_lock lock(m_mtx);
m_newData = false;
}
}
private:
std::condition_variable_any m_cv;
std::shared_mutex m_mtx;
bool m_newData{false}; // To prevent spurious wakeups
};
class Example {
public:
// Multiple threads will call this function in the same instance of Example
void ConsumerLoop()
{
int latestData{0};
while (true){
m_signaller.Wait([this, &latestData](){ latestData = m_latestData; });
// process latestData...
// I want to make sure latestData here is always the latest
// (It's OK to miss a few signals in between if its off processing this latest data)
}
}
// One thread will be using this to signal new data
void ProducerLoop(){
while(true){
int newData = rand();
m_signaller.Signal([this, newData](){ m_latestData = newData; });
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
private:
Signaller m_signaller;
int m_latestData;
};
My main issue (I think) is how to prevent spurious wakeups, while preventing repeated data from waking up the same thread. I've thought about using some sort of counter within each thread to keep track of whether it's receiving the same data, but couldn't get anywhere with that idea (unless I perhaps make some sort of map using std::this_thread::get_id?). Is there a better way to do this?
EDIT:
Expanding on my map of thread ID's idea, I think I've found a solution:
#include <functional>
#include <shared_mutex>
#include <condition_variable>
#include <unordered_map>
#include <thread>
class Signaller {
public:
// Used by producer, will hold on to the mutex uniquely as it modifies data
void Signal(const std::function<void()>& fnIn) {
std::unique_lock lock(m_mtx);
fnIn();
m_ctr++;
m_cv.notify_all();
}
void RegisterWaiter(){
std::unique_lock lock(m_mtx);
auto [itr, emplaced] = m_threadCtrMap.try_emplace(std::this_thread::get_id(), m_ctr);
if (!emplaced) {
itr->second = m_ctr;
}
}
// Used by consumers, will only hold shared mutex to read data
void Wait(const std::function<void()>& fnIn) {
std::shared_lock lock(m_mtx);
m_cv.wait(lock, [this](){ return m_threadCtrMap[std::this_thread::get_id()] != m_ctr; });
fnIn();
m_threadCtrMap[std::this_thread::get_id()] = m_ctr;
}
private:
std::condition_variable_any m_cv;
std::shared_mutex m_mtx;
std::uint32_t m_ctr{0};
std::unordered_map<std::thread::id, std::uint32_t> m_threadCtrMap; // Stores the last signalled ctr for that thread
};
class Example {
public:
// Multiple threads will call this function in the same instance of Example
void ConsumerLoop()
{
int latestData{0};
m_signaller.RegisterWaiter();
while (true){
m_signaller.Wait([this, &latestData](){ latestData = m_latestData; });
}
}
// One thread will be using this to signal new data
void ProducerLoop(){
while(true){
int newData = rand();
m_signaller.Signal([this, newData](){ m_latestData = newData; });
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
private:
Signaller m_signaller;
int m_latestData;
};
Here's my implementation:
#include <unordered_map>
#include <condition_variable>
#include <shared_mutex>
#include <thread>
/*
Example usage:
struct MyClass {
MultiCVSignaller m_signaller;
int m_latestData;
std::atomic<bool> m_stop{false};
~MyClass(){
m_stop = true;
m_signaller.Shutdown();
}
void FuncToWaitOnData() { // e.g. Multiple threads call this fn to "subscribe" to the signal
auto& signalCtr = m_signaller.RegisterListener();
while(!m_stop.load(std::memory_order_relaxed)) {
int latestDataInLocalThread;
// WaitForSignal() calls the provided function while holding on to the shared mutex
m_signaller.WaitForSignal(signalCtr, [this, &latestDataInLocalThread](){
latestDataInLocalThread = m_latestData;
});
// Make use of latest data...
}
}
void ProducerLoop() {
while(!m_stop.load(std::memory_order_relaxed)) {
// Signal() holds on to the mutex uniquely while calling the provided function.
m_signaller.Signal([&latestData](){
m_latestData = rand();
});
}
}
};
*/
class MultiCVSignaller
{
public:
using SignalCtr = std::uint32_t;
public:
MultiCVSignaller() = default;
~MultiCVSignaller() { Shutdown(); }
/*
Call to set and signal shutdown state, cancelling waits (and skipping the functions provided if any)
This should be added in the class' destructor before threads are joined.
*/
void Shutdown() {
std::unique_lock lock(m_mtx);
m_shutdown = true;
m_cv.notify_all();
}
// Calls the function if specified while holding on to the mutex with a UNIQUE lock
template<class Func = void(*)()>
void Signal(Func fnIn = +[]{})
{
std::unique_lock lock(m_mtx);
fnIn();
m_ctr++;
m_cv.notify_all();
}
MultiCVSignaller::SignalCtr& RegisterListener(){
std::unique_lock lock(m_mtx);
auto [itr, emplaced] = m_threadCtrMap.try_emplace(std::this_thread::get_id(), m_ctr);
if (!emplaced) {
itr->second = m_ctr;
}
return itr->second;
}
/*
Calls the optional function while holding on to the SHARED lock when signalled. The signalCtr argument should be provided by the return of RegisterListener() (see example)
*/
template<class Func = void(*)()>
void WaitForSignal(MultiCVSignaller::SignalCtr& signalCtr, Func fnIn = +[]{})
{
std::shared_lock lock(m_mtx);
m_cv.wait(lock, [this, &signalCtr](){ return ( m_shutdown || signalCtr != m_ctr); });
if (!m_shutdown)
{
fnIn();
signalCtr = m_ctr;
}
}
private:
std::condition_variable_any m_cv;
std::shared_mutex m_mtx;
bool m_shutdown{false};
SignalCtr m_ctr{0}; // Latest ctr from Signal()
// This map stores the signal count received for registered listeners.
// We use an unordered_map as references are never invalidated (unless erased),
// which is not the case for a vector
std::unordered_map<std::thread::id, SignalCtr> m_threadCtrMap;
};

Error when creating an interrupt-able thread

I want to create a thread that can be interrupted while waiting (it waits data from other processes and I want to stop the process in nice way).
I've read the 9.2 part of C++ Concurrency in Action 2nd Edition, and I've tried to implement that ideas, but I've some problem and I don't know where to check.
This is my code based on that example:
#include <iostream>
#include <stdexcept>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <future>
// Exception that should be raised when there's an interruption.
// It's raised when the thread is interrupted, so we can catch
// it and finish the thread execution.
class InterruptedException : public std::runtime_error {
public:
InterruptedException(const std::string& message) : std::runtime_error(message) {}
virtual ~InterruptedException() {}
};
// Interrupt flag. This class represents a local-thread flag that
// tells if the thread is interrupted or not.
class InterruptFlag {
public:
InterruptFlag() :
m_threadConditionVariable(nullptr),
m_threadConditionVariableAny(nullptr) {}
void set() {
m_flag.store(true, std::memory_order_relaxed);
std::lock_guard<std::mutex> lk(m_setClearMutex);
if (m_threadConditionVariable) {
m_threadConditionVariable->notify_all();
}
else if (m_threadConditionVariableAny) {
m_threadConditionVariableAny->notify_all();
}
}
template <typename Lockable>
void wait(std::condition_variable_any& cv, Lockable& lk) {
struct CustomLock {
InterruptFlag* m_self;
Lockable& m_lk;
CustomLock(InterruptFlag* self, std::condition_variable_any& cond, Lockable& lk) :
m_self(self),
m_lk(lk) {
m_self->m_setClearMutex.unlock();
m_self->m_threadConditionVariableAny = &cond;
}
void unlock() {
m_lk.unlock();
m_self->m_setClearMutex.unlock();
}
void lock() {
std::lock(m_self->m_setClearMutex, lk);
}
~CustomLock() {
m_self->m_threadConditionAny = nullptr;
m_self->m_setClearMutex.unlock();
}
};
CustomLock cl(this, cv, lk);
InterruptPoint();
cv.wait(cl);
InterruptPoint();
}
void setConditionVariable(std::condition_variable& cv) {
std::lock_guard<std::mutex> lk(m_setClearMutex);
m_threadConditionVariable = &cv;
}
void clearConditionVariable() {
std::lock_guard<std::mutex> lk(m_setClearMutex);
m_threadConditionVariable = nullptr;
}
bool isSet() const {
return m_flag.load(std::memory_order_relaxed);
}
private:
std::atomic<bool> m_flag;
std::condition_variable* m_threadConditionVariable;
std::condition_variable_any* m_threadConditionVariableAny;
std::mutex m_setClearMutex;
};
// Thread-local interrupt flag instance. The variable should be
// created for every thread, since it's thread_local.
thread_local InterruptFlag ThisThreadInterruptFlag;
// Convenience class for cleaning the flag due to RAII.
struct ClearConditionVariableOnDestruct {
~ClearConditionVariableOnDestruct() {
ThisThreadInterruptFlag.clearConditionVariable();
}
};
// Function that throws the exception that tells that the thread
// is interrupted. For doing it checks the state of ThisThreadInterruptFlag.
void InterruptionPoint() {
if (ThisThreadInterruptFlag.isSet()) {
throw InterruptedException("Interrupted");
}
}
// Function that must be used inside the thread function body for waiting.
// It waits for the condition variable, when it notifies from other threads,
// but it also notifies if the thread is interrupted.
void InterruptibleWait(std::condition_variable& cv, std::unique_lock<std::mutex>& lk) {
InterruptionPoint();
ThisThreadInterruptFlag.setConditionVariable(cv);
ClearConditionVariableOnDestruct guard;
InterruptionPoint();
cv.wait_for(lk, std::chrono::milliseconds(1));
InterruptionPoint();
}
// This class represents the interruptible thread. It adds a interrupt()
// method that when called interupts the thread execution, if it's waiting
// at some point where InterruptibleWait function is locked.
class Interruptible {
public:
template <typename FunctionType>
Interruptible(FunctionType f) {
std::promise<InterruptFlag*> p;
m_internalThread = std::thread([f, &p]() {
p.set_value(&ThisThreadInterruptFlag);
try {
f();
}
catch (InterruptedException) {
}
});
m_flag = p.get_future().get();
}
void join() {
m_internalThread.join();
}
void detach() {
m_internalThread.detach();
}
bool joinable() const {
return m_internalThread.joinable();
}
void interrupt() {
if (m_flag) {
m_flag->set();
}
}
private:
std::thread m_internalThread;
InterruptFlag* m_flag;
};
std::mutex mtx;
std::unique_lock<std::mutex> lk(mtx);
int main(int argc, char* argv[]) {
std::cout << "Interrupting thread example" << std::endl;
bool test = false;
std::condition_variable cv;
auto f = [&cv, &test]() {
test = true;
InterruptibleWait(cv, lk);
// Since it locks forever, it should never reach this point.
test = false;
};
Interruptible interruptibleThread(f);
std::this_thread::sleep_for(std::chrono::milliseconds(30));
// We interrupt the function while it's blocked in InterruptibleWait
interruptibleThread.interrupt();
interruptibleThread.join();
std::cout << "test value is " << std::boolalpha << test << ". It should be true." << std::endl;
return 0;
}
Basically I create a Interruptible class representing a thread that can be interrupted. I interrupt it during its execution by calling its interrupt() method. The thread can be interrupted if it's locked with in a InterruptibleWait function call. This function behave like a std::condition.wait(), in fact it wants a reference to it, but it also handle the interruption flag.
If I start the program. I obtain an error from Visual Studio when running.
I don't know what I'm doing wrong. What should I do in order to make InterruptibleWait work correctly?
My best guess based on the given information:
The exception isn't caught in the thread entry point function, and escapes that function. When this happens in a thread started by std::thread, abort is called for you (indirectly through std::terminate) by the std::thread implementation, as required by the standard. To fix this, try catching all exceptions in the function passed to std::thread.
See the cppreference articles on std::thread and std::terminate

Condition variable should be used or not to reduce missed wakeups

I have two threads, one is the producer and other is consumer. My consumer is always late (due to some costly function call, simulated in below code using sleeps) so I have used ring buffer as I can afford to loose some events.
Questions:
I am wondering if it would be better to use condition variable instead of what I currently have : continuous monitoring of the ring buffer size to see if the events got generated. I know that the current while loop of checking the ring buffer size is expensive, so I can probably add some yield calls to reduce the tight loop. I want to reduce the chances of dropped events.
Can I get rid of pointers? In my current code I am passing pointers to my ring buffer from main function to the threads. Wondering if there is any fancy or better way to do the same?
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <atomic>
#include <boost/circular_buffer.hpp>
#include <condition_variable>
#include <functional>
std::atomic<bool> mRunning;
std::mutex m_mutex;
std::condition_variable m_condVar;
long int data = 0;
class Detacher {
public:
template<typename Function, typename ... Args>
void createTask(Function &&func, Args&& ... args) {
m_threads.emplace_back(std::forward<Function>(func), std::forward<Args>(args)...);
}
Detacher() = default;
Detacher(const Detacher&) = delete;
Detacher & operator=(const Detacher&) = delete;
Detacher(Detacher&&) = default;
Detacher& operator=(Detacher&&) = default;
~Detacher() {
for (auto& thread : m_threads) {
thread.join();
}
}
private:
std::vector<std::thread> m_threads;
};
void foo_1(boost::circular_buffer<int> *cb)
{
while (mRunning) {
std::unique_lock<std::mutex> mlock(m_mutex);
if (!cb->size())
continue;
int data = cb[0][0];
cb->pop_front();
mlock.unlock();
if (!mRunning) {
break;
}
//simulate time consuming function call
std::this_thread::sleep_for(std::chrono::milliseconds(16));
}
}
void foo_2(boost::circular_buffer<int> *cb)
{
while (mRunning) {
std::unique_lock<std::mutex> mlock(m_mutex);
cb->push_back(data);
data++;
mlock.unlock();
//simulate time consuming function call
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
int main()
{
mRunning = true;
boost::circular_buffer<int> cb(100);
Detacher thread_1;
thread_1.createTask(foo_1, &cb);
Detacher thread_2;
thread_2.createTask(foo_2, &cb);
std::this_thread::sleep_for(std::chrono::milliseconds(20000));
mRunning = false;
}
The producer is faster (16x) than the consumer, so ~93% of all events will always be discarded.

Wake up of the thread is time consuming

#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <iostream>
#include <deque>
#include <functional>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <atomic>
#include <vector>
//thread pool
class ThreadPool
{
public:
ThreadPool(unsigned int n = std::thread::hardware_concurrency())
: busy()
, processed()
, stop()
{
for (unsigned int i=0; i<n; ++i)
workers.emplace_back(std::bind(&ThreadPool::thread_proc, this));
}
template<class F> void enqueue(F&& f)
{
std::unique_lock<std::mutex> lock(queue_mutex);
tasks.emplace_back(std::forward<F>(f));
cv_task.notify_one();
}
void waitFinished()
{
std::unique_lock<std::mutex> lock(queue_mutex);
cv_finished.wait(lock, [this](){ return tasks.empty() && (busy == 0); });
}
~ThreadPool()
{
// set stop-condition
std::unique_lock<std::mutex> latch(queue_mutex);
stop = true;
cv_task.notify_all();
latch.unlock();
// all threads terminate, then we're done.
for (auto& t : workers)
t.join();
}
unsigned int getProcessed() const { return processed; }
private:
std::vector< std::thread > workers;
std::deque< std::function<void()> > tasks;
std::mutex queue_mutex;
std::condition_variable cv_task;
std::condition_variable cv_finished;
unsigned int busy;
std::atomic_uint processed;
bool stop;
void thread_proc()
{
while (true)
{
std::unique_lock<std::mutex> latch(queue_mutex);
cv_task.wait(latch, [this](){ return stop || !tasks.empty(); });
if (!tasks.empty())
{
// got work. set busy.
++busy;
// pull from queue
auto fn = tasks.front();
tasks.pop_front();
// release lock. run async
latch.unlock();
// run function outside context
fn();
++processed;
latch.lock();
--busy;
cv_finished.notify_one();
}
else if (stop)
{
break;
}
}
}
};
#endif // THREADPOOL_H
I have the above thread pool implementation using a latch. However, every time I add a task through the enqueue call, the overhead is quite large, it takes about 100 micro seconds.
How can I improve the performance of the threadpool?
Your code looks fine. The comments above in your question about compiling with release optimizations on are probably correct and all you need to do.
Disclaimer: Always measure code first with appropriate tools to identify where the bottlenecks are before attempting to improve it's performance. Otherwise, you might not get the improvements you seek.
But a couple of potential micro-optimizations I see are this.
Change this in your thread_proc function
while (true)
{
std::unique_lock<std::mutex> latch(queue_mutex);
cv_task.wait(latch, [this](){ return stop || !tasks.empty(); });
if (!tasks.empty())
To this:
std::unique_lock<std::mutex> latch(queue_mutex);
while (!stop)
{
cv_task.wait(latch, [this](){ return stop || !tasks.empty(); });
while (!tasks.empty() && !stop)
And then remove the else if (stop) block and the end of the function.
The main impact this has is that it avoids the extra "unlock" and "lock" on queue_mutex as a result of latch going out of scope on each iteration of the while loop. The changing of if (!tasks.empty()) to while (!tasks.empty()) might save a cycle or two as well by letting the currently executing thread which has the quantum keep the lock and try to deque the next work item.
<opinion>
One final thing. I'm always of the opinion that the notify should be outside the lock. That way, there's no lock contention when the other thread is woken up by the thread that just updated the queue. But I've never actually measured this assumption, so take it with a grain of salt:
template<class F> void enqueue(F&& f)
{
queue_mutex.lock();
tasks.emplace_back(std::forward<F>(f));
queue_mutex.unlock();
cv_task.notify_one();
}

How to use the following Semaphore code

I am reading about Semaphores. From what I understand is that a Semaphore allows only a certain number of threads to access a specific resource. I came across this post which explains how to create a simple semaphore class using condition variables and a mutex. The code for ease of access is pasted here from that link
#include <mutex>
#include <condition_variable>
class Semaphore {
public:
Semaphore (int count_ = 0)
: count(count) {}
inline void notify()
{
std::unique_lock<std::mutex> lock(mtx);
count++;
cv.notify_one();
}
inline void wait()
{
std::unique_lock<std::mutex> lock(mtx);
while(count == 0){
cv.wait(lock);
}
count--;
}
private:
std::mutex mtx;
std::condition_variable cv;
int count;
};
My question is how would I use the above class to make this method accessible to only 3 threads at a time
void SomeFunction
{
------------------------------> Only 3 threads should be allowed access to this function concurrently
int a = getSomeValue();
//Do something useful
------------------------------>
}
I am thinking that I would do something like this
Semaphore s(3);
void SomeFunction
{
s.wait();
int a = getSomeValue();
//Do sometning useful
s.notify();
}
However I am not sure when wait() and notify() would be called ?
It would be better to use RAII idiom for a semaphore:
class SemaphoreLock
{
public:
SemaphoreLock(Semaphore& s)
: _pS(&s)
{
_pS->wait();
}
~SemaphoreLock()
{
_pS->notify();
}
private:
Semaphore* _pS;
};
Semaphore s(3);
void SomeFunction()
{
SemaphoreLock sl(s);
// implement the function here
}
If SemaphoreLock object is declared in the very beginning of the body of the function, then wait() would be called upon entering the function and notify() would be called just before exiting the function, also in the case if an exception is thrown and stack unwinding is not terminated.
An even better solution could be in renaming the methods of Semaphore: wait into lock and notify into unlock. In this case one would be able to use std::lock_guard<Semaphore> in place of self-written SemaphoreLock class.