Do threads share some class fields? - c++

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.

Related

moving an object to a different thread

My application uses a custom serialization mechanism.
Phase 1) The mechanism loads clusters of data on a separate thread, creates all appropriate objects there and so on.
Phase 2) Once they are all fully deserialized, it hands them over to the main application thread and finishes the serialization there by for example setting up connections between objects etc.
This mechanism is a new addition to my framework – before that I was deserializing everything on the main thread.
The problem I have is that some of the objects that are created during deserializatiuon are Qt objects ( a bunch of widgets basically ).
They all record the ids of a thread they were created on. And when the time comes for “phase 2”, these objects start complaing that they all don’t belong to this thread and therefore can have no signals sent etc.
So I found a method on QObject, called ‘moveToThread’. The little bugger’s not very helpful though, as it performs a check and prevents from moving objects from a different thread to the current thread ( WHY scuh a constraint, I have no clue ).
Does anyone have an idea how can I go about this? I can guarantee that the objects will only be createad on a separate thread, and from that point on they will all be living and operating on the main thread.
Thanks,
Paksas
Instances of a QObject, or any instance of subclasses of QObjects must be handled with care when it comes to multi-threading.
Take a look to this page for an introduction to the topic.
Suppose that your application consists of two threads A and B.
Suppose that thread A creates an object QObject instance.
instance is said to live in thread A. This means that:
- it can directly send and receive signals to all other objects living in thread A.
- all calls done to method of myInstance from thread A are thread-safe
Accessing instance from the other thread B, on the other hand:
- is not thread safe (you must take care of race conditions).
- Moreover signals emitted by instance and connected to slot of objects in thread B are not direct: the slot execution is deferred to a later moment by copying all the method parameters and placing everything in an event to be executed by thread B event queue.
Given this, the solution that you can exploit is the following.
SubClass is a subclass of a QObject.
class SubClass : public QObject{
Q_OBJECT
[...]
}
The thread A will run the following method to deserialize and populate memory with SubClass instances
void methodA(){ /this method is executed by thread A
QThread* threadB; //a reference to the QThread related to thread B
[...]
MyQObject* instance = someFactoryMethod();
//we push the ownership of instance from thrad A to thread B
instance->moveToThread( threadB );
//do something else
}
Notice however that this might not be sufficient if thread A needs to perform other operations on instance. In particular it might happens that thread A will trigger some singals defined in MyQObject. This is not allowed since now thread A is not the owner of instance anymore.
In this case you need to defer such operation and ask thread B to perform it. This is realized by using the QMetaObject::invokeLater method.
InvokeLater allows you to call a specific slot asking thread B to execute it.
Suppose that ClassInB is a class whose instances are used in thread B
class ClassInB : public QObject{
Q_OBJECT
public:
[...]
slots:
void complexOperation(MyQObject* o){
[...]
emitSomeSignal();
}
signals:
void someSignal();
}
after moving instance to thread B we need to execute complexOperation() on an instance of ClassInB living in thread B which, in turn, will also emit someSignal().
void methodA(){ //this method is executed by thread A
QThread* threadB; //a reference to the QThread related to thread B
ClassInB* instanceOnB; //a reference to a ClassInB instance living in thread B
[...]
MyQObject* instance = someFactoryMethod();
//we push the ownership of instance from thread A to thread B
instance->moveToThread( threadB );
//we ask thread B to perform some operation related to instance
QMetaObject::invokeLater(instanceOnB, "complexOperation", Q_ARG(MyQObject*, instance) );
}
To be able to use MyQObject* as a parameter of invokeLater we need to register it to the Meta framework. You will need to:
add Q_DECLARE_METATYPE(MyQObject*) in the .cpp defining MyQObject
call once, before using the mechanism (e.g. in the main), qRegisterMetaType<MyQObject*>();
Simply replace your function calls with QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method) to run a slot in another thread, since according to documentation, it executes the slot from the target thread.
This way you don't need to bother with changing your code in any way, or wondering if your current object is in the same thread or not, etc.

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

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.

Boost thread questions

I am trying to do the followings
class a{
public:
void Start();
void Tick();
bool IsTimeOut;
};
void a::Start()
{
boost::thread thread1(boost::bind(&a::Tick,this));
}
void a::Tick()
{
while(!IsTimeOut)
{
boost::this_thread::sleep(boost::posix_time::millisec(1000));
}
}
My environment is vs2005 and win7.
However, I always got the access violation in the debug.
An access violation in this case would indicate that the thread is running beyond the lifetime of the a object.
IsTimeOut needs to either be atomic or protected by a mutex if it is written by another thread, otherwise your program might not work correctly, but this shouldn't cause the access violation.
You are destroying the boost::thread object immediately, and thus detaching the thread, so you have no way of waiting for it to finish. I would suggest storing the thread object as a member variable of a, and either joining with it in the destructor of a or providing an explicit wait() member function that joins with the thread.
IsTimeOut should be volatile if accessed from multiple threads, i.e.
volatile bool IsTimeOut;
Take a look at this DDJ article.
If you show more of your code and also explain how the IsTimeOut is changed it might be easier to say what goes wrong. In general, it looks like you have multiple threads and the first creates a, but what does that thread do then? Will a go out of scope and thus be destroyed? If so, then the timer thread will for sure have an access violation as the object is no longer available.

Singleton and thread safety

When talking about Singletons and threadsafe-ty issues concerning race conditions in creating the singleton instance, which thread are we talking about?
Using this as example, assume I have a MyApp that uses a Singleton
class MyApp
{
MySingleton oneAndOnly;
int main() // application entry point
{
oneAndOnly = MySingleton::GetInstance();
}
void SpawnThreads()
{
for(int i = 0; i < 100; i++)
{
Thread spawn = new Thread(new ThreadStart(JustDoIt));
spawn.Start();
}
}
void JustDoIt()
{
WaitRandomAmountOfTime(); // Wait to induce race condition (maybe?) for next line.
MySingleton localInstance = MySingleton::GetInstance();
localInstance.DoSomething();
}
}
Is it talking about:
when I open the MyApp.exe once, and
then once more again, trying to have
both opened?
Or is it talking about the threads spawned by MyApp? What if MyApp does
not spawn threads?
In Windows threads exist solely within the scope of a process, i.e. the running instance of an application. So thread safety means making sure that shared resources are accessed sequentially from multiple threads within a given process.
In more general terms, race conditions occur as a result of concurrency regardless of scope. For example a distributed application that exposes a shared resource to external processes, is still subject to race conditions if access to that resource isn't properly regulated.

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.