C++ Gtk threading. Am I doing it right? - c++

I have a gtkmm application and I'm trying to put some long running tasks into separate threads so they don't lock the GUI. Here's a tutorial I've based my design on:
http://www.velvetcache.org/2008/09/30/gtkmmglibmm-thread-example
I use Glib::Dispatcher signals to notify the GUI thread when the work is done or something needs to be updated, however I'm not sure how to pass the data between the worker thread and GUI thread. So far I've been passing a pointer to the class which creates the worker to the worker and then modifying public members of the class, but something tells me it's not the most correct to do it. Here's an example:
class Some_GUI_class
{
public:
std::string thread_message;
private:
Worker_class* worker;
void start_worker()
{
if (worker != NULL) return;
worker = new Worker_class(this);
worker->sig_message.connect(sigc::mem_fun(*this, &Some_GUI_class::display_message_from_thread);
worker.start();
}
void display_message_from_thread()
{
some_label->set_text(thread_message);
}
}
class Worker_class
{
public:
Worker_class(Some_GUI_class* gui_class) : gui_class(gui_class)
{}
void start()
{
thread = Glib::Thread::create(sigc::mem_fun(*this, &Worker_class::run), true);
}
Glib::Dispather sig_message;
protected:
Glib::Thread* thread;
Glib::Mutex mutex;
Some_GUI_class* gui_class;
void run()
{
// ...
gui_class->thread_message = "Message from a thread!";
sig_message();
}
}
This essentialy works, but I guess if the GUI thread wanted to modify thread_message at the same time there would be a problem? Is it safe to do it like this then as long as I'm sure the variables are only modified by a single thread or is there a better way?

You have a race condition. Even if your gui thread doesn't modify thread_message, allowing the GUI thread to read it while another thread is modifying it is not going to give you long term happiness. This is because std::string is not itself protected from multiple threads accessing it, and has multiple internal fields. If one thread is in the process of modifying one of its internal fields, while another is reading them, the internal state will not be consistent from the point of view of the second.
You can use a mutex in the GUI class to protect access to the variables which might be accessed by another thread. Lock and unlock the mutex in get/set routines, and use those routines for all other accesses to ensure that only one thread gets to access or modify the variables at one time.

Generally mutex usage is not enough to achieve the desired behaviour. The same worker thread (or another one if you have it) could want to send another message while first one had not been processed by the main thread yet. That is why in addition to mutex you should use message queue (e.g. object of std::deque<std::string> class) instead of just a std::string Some_GUI_class::thread_message variable to avoid this kind of message loss.

Related

Callbacks to virtual functions

I am doing some work with threading on an embedded platform. This platform provides a Thread class, and it has a start method that takes a function pointer, like this:
void do_in_parallel() {
// Some stuff to do in a new thread
}
Thread my_thread;
my_thread.start(do_in_parallel);
The problem is there is no way to pass parameters in.1 I want to solve this by creating an abstract class, call it Thread2, that extends Thread (or it could just have a Thread as instance data).
Thread2 would have a pure virtual function void run() and the goal was to pass that to Thread::start(void*()), except I soon learned that member function pointers have a different type and can't be used like this. I could make run() static, but then I still can't have more than one instance, defeating the whole purpose (not to mention you can't have a virtual static function).
Are there any workarounds that wouldn't involve changing the original Thread class (considering it's a library that I'm stuck with as-is)?
1. Global variables are a usable workaround in many cases, except when instantiating more than one thread from the same function pointer. I can't come up with a way to avoid race conditions in that case.
Write a global thread pool.
It maintains a queue of tasks. These tasks can have state.
Whe you add a task to the queue, you can choose to also request it get a thread immediately. Or you can wait for threads in the pool to be finished what they are doing.
The threads in the pool are created by the provided Thread class, and they get their marching instructions from the pool. For the most part, they should pop tasks, do them, then wait on another task being ready.
If waiting isn't permitted, you could still have some global thread manager that stores state for the threads.
The pool/manager returns the equivalent of a future<T> augmented with whatever features you want. Code that provides tasks interacts with the task through that object instead of the embedded Thread type.
A simple wrapper can be written if locking is permitted
void start(Thread& t, void (*fn)(void*), void* p)
{
static std::mutex mtx; // or any other mutex
static void* sp;
static void (*sfn)(void*);
mtx.lock();
sp = p;
sfn = fn;
t.start([]{
auto p = sp;
auto fn = sfn;
mtx.unlock();
fn(p);
});
}
This is obviously not going to scale well, all thread creations goes through the same lock, but its likely enough.
Note this is exception-unsafe, but I assume that is fine in embedded systems.
With the wrapper in place
template<typename C>
void start(Thread& t, C& c)
{
start(t, [](void* p){
(*(C*)p)();
}, &c);
}
Which allows any callable to be used. This particular implementation places the responsibility of managing the callable's lifetime on the caller.
You can create your own threaded dispatching mechanism (producer-consumer queue) built around the platform specific thread.
I assume that you have the equivalent facilities of mutex and conditional variables/signalling mechanism for the target platform.
Create a thread safe queue that can accept function objects.
The run method creates a thread and waits on the queue.
The calling thread can call post()/invoke() method that simply insert a function object to the queue.
The function object can have the necessary arguments passed to the caller thread.

Put all database operations in a specific thread using Qt

I have a console application where after a timeout signal, a 2D matrix (15*1200) should be parsed element-by element and inserted to a database. Since the operation is time-consuming, I perform the insertion in a new thread using QConcurrent::run.
However, due to timeout signals, several threads may start before one finished, so multiple accesses to the database may occur.
As a solution, I was trying to buffer all database operations in a specific thread, in other words, assign a specific thread to the database class, but do not know how to do so.
Your problem is a classical concurrent data analysis problem. Have you tried using std::mutex? Here's how you use it:
You create some variable std::mutex (mutex = mutual exclusion) that's accessible by all the relevant threads.
std::mutex myLock;
and then, let's say that the function that processes the data looks like this:
void processData(const Data& myData)
{
ProcessedData d = parseData();
insertToDatabase(d);
}
Now from what I understand, you're afraid that multiple threads will call insertToDatabase(d) simultaneously. Now to solve this issue, simply do the following:
void processData(const Data& myData)
{
ProcessedData d = parseData();
myLock.lock();
insertToDatabase(d);
myLock.unlock();
}
Now with this, if another thread tries to access the same function, it will block until another all other threads are finished. So threads are mutually excluded from accessing the call together.
More about this:
Caveats:
This mutex object must be the same one that all the threads see, otherwise this is useless. So either make it global (bad idea, but will work), or put it in a the class that will do the calls.
Mutex objects are non-copyable. So if you include them in a class, you should either make the mutex object a pointer, or you should reimplement the copy constructor of that class to prevent copying that mutex, or make your class noncopyable using delete:
class MyClass
{
//... stuff
MyClass(const MyClass& src) = delete;
//... other stuff
};
There are way more fancier ways to use std::mutex, including std::lock_guard and std::unique_lock, which take ownership of the mutex and do the lock for you. This are good to use if you know that the call insertToDatabase(d); could throw an exception. In that case, using only the code I wrote will not unlock the mutex, and the program will reach a deadlock.
In the example I provided, here's how you use lock_guard:
void processData(const Data& myData)
{
ProcessedData d = parseData();
std::lock_guard<std::mutex> guard(myLock);
insertToDatabase(d);
//it will unlock automatically at the end of this function, when the object "guard" is destroyed
}
Be aware that calling lock() twice by the same thread has undefined behavior.
Everything I did above is C++11.
If you're going to deal with multiple threads, I recommend that you start reading about data management with multiple threads. This is a good book.
If you insist on using Qt stuff, here's the same thing from Qt... QMutex.

Do threads share some class fields?

This is an example from C++ GUI Programming with Qt 4
I have a thread class:
class Thread : public QThread {
Q_OBJECT
public:
Thread();
void setMessage(const QString &message);
void stop();
protected:
void run();
private:
QString messageStr;
volatile bool stopped;
}
This is the relevant implementation of the the class:
Thread::Thread() {
stopped = false;
}
void Thread::run() {
while (!stopped)
std::cerr << qPrintable(messageStr);
stopped = false;
std::cerr << std::endl;
}
void Thread::stop() {
stopped = true;
}
This class is used in a ThreadDialog class which basically have two private fields Thread threadA and Thread threadB. setMessage function is called separately for them and messageStr is set to "A" and "B". Two buttons are declared inside which have clicked signals connected two to slot functions that start or stop those two threads like this:
void ThreadDialog::startOrStopThreadA() {
if (threadA.isRunning()) {
threadA.stop();
threadAButton->setText(tr("Start A"));
} else {
threadA.start();
threadAButton->setText(tr("Stop A"));
}
}
The function for threadB is the same. The problem is this, quoting directly from the book: "The stopped variable is declared volatile because it is accessed from different threads and we want to be sure that it is freshly read every time it is needed. If we omitted the volatile keyword, the compiler might optimize access to the variable, possibly leading to incorrect results."
I can't understand why these two threads would access the same field. Aren't they different instances so they have their own field stopped? Furthermore if stopped field is shared why isn't messageStr field shared too?
I can't understand why these two threads would access the same field. Aren't they different instances
so they have their own field stopped? Furthermore if stopped field is shared why isn't messageStr
field shared too?
That's not what they are saying. The field is not shared among different instances, regardless of whether there are threads involved or not. However an instance might be accessed from different threads, in that regard, the fields might be "shared" among different threads.
They are talking about the case when some other thread wishes to call threadA.stop()
If you have this code:
Thread threadA;
threadA.start();
...
threadA.stop();
There are 2 threads involved:
The thread that runs the above code
The newly created threadA that is started with the threadA.start() call
Now volatile bool stopped is accessed by thread 2 in it's run() function, and it's accessed from thread 1 when it calls threadA.stop().
This is a common confusion in multithreading. You are confusing the thread object class Thread : public QThread with the thread of execution (ie executing instructions).
There is one thread of execution which is running the code ThreadDialog::startOrStopThreadA
There is another thread of execution which is running Thread::run() and which is started by threadA.start().
Both of these threads have access to messageStr and stopped
The two instances threadA and threadB do not share stopped. They are different instances if a same class.
About this statement :
The stopped variable is declared volatile because it is accessed from
different threads and we want to be sure that it is freshly read every
time it is needed.
It means that the stopped variable is accessed from two different running threads. Here the two threads are the main application thread and the one in the run() function. It's unsafe to access the same variable from two different threads.

Passing data from caller thread to the method in another boost::thread

I have rather a noob question regarding concurrency in C++ (Using Boost threads) on which I haven't found a clear answer.I have a worker class which runs in a separate thread.I init the worker on the start of the program only once.This worker is "lazy" and does some data encoding only when it receives it from the calling thread.In the worker I have a public method:
void PushFrame(byte* data);
which pushes the data to the std::stack member variable so the worker can access it each time new data object is pushed there.
What I don't understand is how such an interaction generally done? Can I just call PushFrame() from the caller thread and pass the argument? Or do I have to access the methods in the worker in some special way?
Usually you use a producer-consumer-queue for this type of work.
Whenever the worker thread runs out of work he wait()s on a boost::condition_variable which is protected by the same boost::mutex as the stack holding the data for the worker thread (you might want to use a queue here instead to minimize the risk of unfair work scheduling).
Your PushFrame() function now calls notify_one() on that condition variable whenever it inserts new data into the stack. That way, the worker thread will truly sleep (i.e. the OS scheduler will probably not give it any timeslice) until there is actually work to be done.
The easiest thing to get wrong here is the locking of the mutex protecting both the stack and the condition_variable. Besides avoiding races on the data structures, you also need to take care that the condition_variable does not miss a notify call and therefore might get stuck waiting while there actually is more work available.
class Worker {
void PushFrame(byte* data)
{
boost::lock_guard<boost::mutex> lk(m_mutex);
// push the data
// ...
m_data_cond.notify_one();
}
void DoWork()
{
while(!done) {
boost::unique_lock<boost::mutex> lk(m_mutex);
// we need a loop here as wait() may return spuriously
while(is_out_of_work()) {
// wait() will release the mutex and suspend the thread
m_data_cond.wait(lk);
// upon returning from wait() the mutex will be locked again
}
// do work from the queue
// ...
}
}
boost::mutex m_mutex;
boost::condition_variable m_data_cond;
[...]
};

understanding a qthread subclass's run method and thread context

i have an encoder class with lots of methods . this is a subclass of Qthread. i am new to multi-threading and
trying to understand how this class is
threading its methods
... i understand to thread a method it has to be in a subclass of qthread. and the run of this implements the threaded code for this class. And the thread starts only when a call to start method on the object of this class is made.
Question : firstly what do you infer
from the this run implementation
void Encoder::run(void)
{
VERBOSE(VB_DEBUG, "Encoder::run");
if (WILL_PRINT(VB_DEBUG))
print_stats_timer_id = QObject::startTimer(kEncoderDebugInterval);
health_check_timer_id = QObject::startTimer(kEncoderHealthCheckInterval);
if (init())
exec();
else
VERBOSE(VB_ERROR, "Encoder::run -- failed to initialize encoder");
QObject::killTimer(health_check_timer_id);
if (print_stats_timer_id)
QObject::killTimer(print_stats_timer_id);
cleanup();
}
Question: what does thread context mean in
relation to its methods .
also
Question: what would happen If a method of this
class is called before this class's
thread has started
The class you have written creates a thread and initializes a QObject::timer. It then goes on to call a user defined init() function then the QThread::exec() function.
My guess is that you intended that exec() would be a user defined function where the actual work is to occur. Be aware that QThread::exec() processes the thread's Qt Event Queue.
Also, on some platforms you may get an "Error creating timer from thread" warning message. I've encountered this error on Windows when the code executed fine on Linux
Also, be aware that your timer will never occur if you do not call the QThread::exec() function or QApplication::processEvents() from within your thread.
Thread context in Qt is the same as any other thread concept. That is, all memory is shared between the threaded code (entered at this point in your "run()" function). And any other context which calls into your object. If this object may ever be executing in a thread and accessed from outside of the thread you must protect the shared data.
Because all data is shared between thread contexts (it's a shared memory multiprocessing model) there is no problem with calling functions before/after/during thread execution. Given that:
The object is fully constructed before you call any method. This is not special to threads, necessarily, unless the object is created in a thread.
Any data member is protected with a mutex lock (I eluded to this in #2). QMutexLocker is a handy stack based RAII way of dealing with mutex locks in Qt.
I believe I fully answered your question here, so I'll go ahead and link to RAII and threading articles I have written on another site, just for further reference.
Edit: specificity about threading scenarios:
class MyThreadedClass : public QThread
{
MyThreadClass(const boost::shared_ptr<SomeOtherClass> &t_object)
: m_object(t_object) {}
void doSomething()
{
// Depending on how this method was called (from main, from internal thread)
// will determine which thread this runs on, potentially complicating thread
// safety issues.
m_object->someThing();
}
void run()
{
// I'm now in a thread!
m_object->someFunction(); // oops! The call to someFunction is occurring from
// a thread, this means that SomeOtherClass must be
// threadsafe with mutex guards around shared
// (object level) data.
// do some other stuff
}
};
int main()
{
MyThreadClass thread(someobjectfromsomewhere);
thread.start(); // MyThreadClass is now running
thread.doSomething(); // The call to doSomething occurs from main's thread.
// This means 2 threads are using "thread", main
// and "thread"'s thread.
// The call to thread.doSomething hits Thread.m_object, which means that
// now multiple threads are also accessing m_object ("thread" and "main").
// This can all get very messy very quickly. It's best to tightly control
// how many threads are hitting an object, and how
}
NOTE: It would be a good idea to investigate QFuture, which is designed to handle this kind of asynchronous task, like an encoder, that you are looking at QFuture will avoid some of the potential threading issues of shared data and deadlocks.