boost::thread passing data between threads - c++

I am attempting to pass data between two sub classes of my main threading class using boost::thread. I am very new to multithreading and in a bit over my head. Right now the code produces the following repeatedly.
Reader Api: 0
Below is my class andd subclass definitions. The threading class is a singleton.
class threading
{
public:
static threading *Instance();
void workerFunc();
void workerFunc2();
void inputWorkerFunc(); // handles input processing
void producer();
void consumer();
int getGlobalVariable() // retrieves the value of globalVariable
{
return (globalVariable);
}
void setGlobalVariable(int set) // sets the value of globalVariable
{
globalVariable = set;
}
class Reader
{
public:
Reader(int waitTime) { _waitTime = waitTime;}
void operator() ()
{
threading *thread = threading::Instance();
int globalVariable = thread->getGlobalVariable();
for (int i=0; i < 10; i++)
{
logMsg("Reader Api: " +Ogre::StringConverter::toString(globalVariable));
// usleep(_waitTime);
boost::this_thread::sleep(boost::posix_time::microseconds(_waitTime));
}
return;
}
private:
int _waitTime;
};
class Writer
{
public:
Writer(int variable, int waitTime)
{
_writerVariable = variable;
logMsg("Writer Variable: " +Ogre::StringConverter::toString(_writerVariable));
_waitTime = waitTime;
}
void operator () ()
{
logMsg("Writer Variable: " +Ogre::StringConverter::toString(_writerVariable));
threading *thread = threading::Instance();
int globalVariable = thread->getGlobalVariable();
for (int i=0; i < 10; i++)
{
// usleep(_waitTime);
boost::this_thread::sleep(boost::posix_time::microseconds(_waitTime));
logMsg("Waittime Variable: " +Ogre::StringConverter::toString(_waitTime));
// Take lock and modify the global variable
boost::mutex::scoped_lock lock(_writerMutex);
globalVariable = _writerVariable;
thread->setGlobalVariable(globalVariable);
_writerVariable++;
// since we have used scoped lock,
// it automatically unlocks on going out of scope
}
logMsg("Writer Variable: " +Ogre::StringConverter::toString(_writerVariable));
// thread->setGlobalVariable(globalVariable);
}
private:
int _writerVariable;
int _waitTime;
static boost::mutex _writerMutex;
};
protected:
threading();
threading(const threading&);
threading& operator= (const threading&);
private:
static threading *pInstance;
int globalVariable;
boost::mutex mutex;
boost::condition_variable condvar;
typedef boost::unique_lock<boost::mutex> lockType;
double value;
int count;
};
Here is how I am calling the classes in my main code:
threading *thread = threading::Instance();
threading::Reader reads(100);
threading::Writer writes1(100, 200);
threading::Writer writes2(200, 200);
boost::thread readerThread(reads);
boost::thread writerThread1(writes1);
boost::this_thread::sleep(boost::posix_time::microseconds(100));
boost::thread writerThread2(writes2);
readerThread.join();
writerThread1.join();
writerThread2.join();

You're obviously missing a decent synchronization mechanism like a (global) mutex, to prevent race conditions with this code:
static std::mutex globalVariableProtector;
int getGlobalVariable() // retrieves the value of globalVariable
{
std::lock_guard<std::mutex> lock(globalVariableProtector);
return (globalVariable);
}
void setGlobalVariable(int set) // sets the value of globalVariable
{
std::lock_guard<std::mutex> lock(globalVariableProtector);
globalVariable = set;
}
Moreover, you actually should consider to place that variable into the producer thread's class, and provide getter/setter functions for it, instead of using a global variable.
I've been sharing the current standard references, rather boost. Boost may have their own mechanisms of lock_guards and Synchronized Data Structures, if you for reason can't use the current c++ standard.

Related

Dereferencing a pointer by multiple threads

In the example below, suppose I have a multithreaded queue i.e. supports multiple writes and reads from different threads (e.g. using mutex). We can see that 1. the pointer this as well as 2. the shared pointer m_mulque are passed to the readers and writers and my question is: Dereferencing the pointers this and m_mulque is thread safe or not? In other words is my following code thread safe or not meaning should I worry about any undefined behaviour if I run this please?
#include <mutex>
#include <queue>
struct multithreaded_queue
{
void push(const std::size_t i)
{
std::lock_guard lock(m_mutex);
m_queue.push(i);
};
void try_pop()
{
std::lock_guard lock(m_mutex);
m_queue.pop();
};
private:
std::queue<std::size_t> m_queue;
mutable std::mutex m_mutex;
};
class example
{
public:
example()
{
m_mulque = std::make_shared<multithreaded_queue>();
};
void run()
{
auto writer = [this]()
{
for (std::size_t i = 0; i < 1000; i++)
{
m_mulque->push(i);
};
};
auto reader = [this]()
{
for (std::size_t i = 0; i < 1000; i++)
{
m_mulque->try_pop();
};
};
std::thread writer1(writer);
std::thread reader1(reader);
std::thread reader2(reader);
writer1.join();
reader1.join();
reader2.join();
};
private:
std::shared_ptr<multithreaded_queue> m_mulque;
};
int main(int argc, char* argv[])
{
example ex;
ex.run(); //Is this thread safe to call?
};

Writing a thread safe optimized Datastore class

I am trying to write a thread safe datastore class.
This class object is shared with between many threads in Generator and Consumer, where the class members can be set or get.
By calling setDatastore() the object is set for usage at different threads.
Below is my code,
#ifndef IF_DATA_STORE_H
#define IF_DATA_STORE_H
#include <mutex>
#include <shared_mutex>
#include <memory>
class DataType1{public:int value;};
class DataType2{public:int value;};
class DataStore
{
public:
DataStore(): _member1(), _member2(){}
~DataStore(){}
// for member1
void setMember1(const DataType1& val)
{
std::unique_lock lock(_mtx1); // no one can read/write!
_member1 = val;
}
const DataType1& getMember1() const
{
std::shared_lock lock(_mtx1); // multiple threads can read!
return _member1;
}
// for member2
void setMember2(const DataType2& val)
{
std::unique_lock lock(_mtx2); // no one can read/write!
_member2 = val;
}
const DataType2& getMember2() const
{
std::shared_lock lock(_mtx2); // multiple threads can read!
return _member2;
}
private:
mutable std::shared_mutex _mtx1;
mutable std::shared_mutex _mtx2;
DataType1 _member1;
DataType2 _member2;
// different other member!
};
// now see where data is generated/consumed!
class Generator
{
public:
void start(){/* start thread!*/}
void setDataStore(std::shared_ptr<DataStore> store)
{
_store = store;
}
void threadRoutine() //this is called from different thread and updating values
{
// some code...
{
_data.value = 10; // keep a local updated copy of data!
_store->setMember1(_data);
}
}
private:
std::shared_ptr<DataStore> _store;
DataType1 _data;
};
class Consumer
{
public:
void start(){/* start thread!*/}
void setDataStore(std::shared_ptr<DataStore> store)
{
_store = store;
}
void threadRoutine() // running a check on datastore every 1sec
{
// some code...
auto val = _store->getMember1();
// do something..
}
private:
std::shared_ptr<DataStore> _store;
};
// fianlly start all!
int main()
{
// somewhere in main thread
std::shared_ptr<DataStore> store;
Consumer c; Generator g;
c.setDataStore(store); c.start();
g.setDataStore(store); g.start();
}
#endif
Questions:
Is there any other way than creating multiple shared mutex for each member?
In Generator.threadRoutine() if I keep a local copy of DataType1 does this cause high memory issues (I see high cpu and memory) when this block called frequently, don't if this is the root cause of it.
Any other better way suggested?

Inserting thread::id and class instance in a map

I have a class:
class IOWorker {
std::thread thread_;
boost::asio::io_service ios_;
boost::optional<boost::asio::io_service::work> work_;
Callback callback_;
// Map of thread::id and this class' instance
typedef std::map<std::thread::id, IOWorker *> IOWorkerThreadMap;
static IOWorkerThreadMap iOWorkerThreadMap;
public:
IOWorker(Callback cb);
~IOWorker();
std::thread::id getThreadId() {
return thread_.get_id();
}
// IO worker threads will call this to fetch their instance
static IOWorker* getIOWorkerInstance (void) {
auto it = iOWorkerThreadMap.find(std::this_thread::get_id());
if (it == iOWorkerThreadMap.end()) {
return nullptr;
}
return (it->second);
}
};
IOWorker::IOWorker (Callback cb) : callback_{cb}
{
work_ = boost::in_place(boost::ref(ios_));
thread_ = std::thread{[this] () {
ios_.run();
}
};
}
In a function executed by the main thread, I'm creating 10 instances of this class and inserting these into the map where thread::id is key and class instance is value.
I'm accessing this map from all the worker threads to fetch their respective class instance by looking up their thread::id in the map. The main thread accesses these instances too, to call some methods, post jobs on ios_, etc.
void startIOWorkers (Callback cb)
{
for (int i = 0; i < 10; ++i) {
IOWorker *iow = new IOWorker{cb};
std::thread::id threadId = iow->getThreadId();
IOWorkerThreadMap.insert(std::make_pair(threadId, iow));
}
}
My question is for below line:
IOWorkerThreadMap.insert(std::make_pair(threadId, iow));
My understanding (could be wrong!) is that iow and threadId in above function, will be "copied" while I'm inserting them in the map and two copies of them will exist.
I want to avoid that, therefore, I would like to know what are the better ways of having a map of thread::id and class instance in this case?
This seems way more complicated than it has to be.
If, as it appears to be the case, you only need to access the map at from thread::this_thread, the language already has a map<thread_id, T> built right in: thread_local.
class IOWorker {
std::thread thread_;
boost::asio::io_service ios_;
boost::optional<boost::asio::io_service::work> work_;
Callback callback_;
static thread_local IOWorker* this_thread_worker_;
public:
IOWorker(Callback cb);
~IOWorker();
// IO worker threads will call this to fetch their instance
static IOWorker* getIOWorkerInstance (void) {
return this_thread_worker_;
}
};
IOWorker::IOWorker (Callback cb) : callback_{std::move(cb)}
{
work_ = boost::in_place(boost::ref(ios_));
thread_ = std::thread{[this] () {
this_thread_worker_ = this;
ios_.run();
};
}
std::vector<IOWorker> startIOWorkers(Callback cb)
{
std::vector<IOWorker> launched_workers;
launched_workers.reserve(10);
for (int i = 0; i < 10; ++i) {
launched_workers.emplace_back(cb);
}
return launched_workers;
}

Modifying member variables with QtConcurrent::run()?

Let's say I have a class MyClass that contains a function that is really complex and slow slowFunction() that I want to be executed in another thread, for this I'm using Qtconcurrent::run, here is a snippet:
void MyClass::startAnalysis() {
//Run slowFunction in another thread
QtConcurrent::run(this, &MyClass::slowFunction);
}
void MyClass:slowFunction() {
for(int i = 0; i < 100; i++) {
qDebug() << this << i;
}
}
The main problem that I'm facing is if slowFunction() performs any operation over a member variable of MyClass I get (eventually) a crash. Also, as in the code above, when I try to output the pointer this I also get a crash!.
Is there anything wrong with modifying member variables inside a function executed by QtConcurrent::run ?
You need to protect the access to your member variables with a QMutex.
void MyClass
{
...
private:
QMutex mutex;
}
Then whenever you access a variable used by your concurrent, you protect it with a lock.
{
QMutexLocker locker(&mutex);
// access variable
}
There is nothing wrong in modifying member variables in a thread or a QConcurrent, but you need to protect it.
In this example if I use a QFuture the class instance stays alive as long as needed.
class MyClass : QObject {
public:
void LongFunction() {
for( int count = 0; count < 5; count++ ) {
sleep( 1 );
std::cout << "Ping long!" << std::endl;
}
}
void run_c() {
QFuture<void> future = QtConcurrent::run(this, &MyClass::LongFunction);
}
};
int main(int argc, char *argv[])
{
MyClass c;
c.run_c();
}

variable visibility in thread synchronization

struct Info {
int a;
int b;
};
class A {
public:
A() {
_info = new Info;
_info->a = 1;
_info->b = 1;
}
void update()
{
std::lock_guard<std::mutex> l(_m);
_info->a = 2;
_info->b = 3;
}
Info* get_info() {
std::lock_guard<std::mutex> l(_m);
return _info;
}
private:
mutable std::mutex _m;
Info* _info;
};
A a;
// in thread 1
a.update();
// in thread 2
Info* i = a.get_info();
std::cout<<i->a<<" "<<i->b<<std::endl;
Does it possible to print 1 3 or 2 1 ?
This is unspecified/undefined behavior
The objects being accessed are not protected by a mutex. The mutex is being held only long enough to read the pointer. The mutex is not held while accessing the contents of the pointer, as such the mutex offers no synchronization with update().