So I am using a QQuickFramebufferObject and QQuickFramebufferObject::Renderer in my Qt application. As mentioned here:
To avoid race conditions and read/write issues from two threads it is important that the renderer and the item never read or write shared variables. Communication between the item and the renderer should primarily happen via the QQuickFramebufferObject::Renderer::synchronize() function.
So I have to synchronize whatever data I render when QQuickFramebufferObject::Renderer::synchronize() is called. However, because many times the data that is sent to the render thread can be quite large I would like to avoid copying that data (which is stored in a DataObject), so for now I am passing a std::shared_ptr<DataObject> in the function and assigning that to a private member of my QQuickFramebufferObject::Renderer class. This approaches works fine, but I am not sure if this is the "correct" way of doing things. What approach can I take in order to share/transfer the data between the GUI thread and the rendering thread?
For data that is too big to copy in the synchronize() method, use a synchronization object to manage access to the data; lock it when writing, release it when finished and lock it in when rendering and access the data directly. You are safe as long as only one thread is accessing the data at a time.
The risk of skipped frames increases the longer the synchronization object is locked. Locking for writing longer than half the optimal render quantum (8.5ms = ~16.7ms/2) will incur dropped frames, but you probably have much more happening in your app so the real number is lower.
Alternatively, you could use a circular buffer for your large data structures with a protected index variable so you can simultaneously write to one structure while reading from another. Increment the index variable when all data is ready to display and call QQuickItem::update().
Related
I'm writing a game engine (for fun), and have a lot of threads running concurrently. I have a class which holds an instance of another class as a private variable, which in turn holds and instance of a different class as a private variable. My question is, which one of these classes should I strive to make thread safe?
Do I make all of them thread safe, and have each of them protect their data with a mutex, do I make just one of them thread safe, and assume that anybody using my code must understand that if you are using underlying classes they aren't inherently thread safe.
Example:
class A {
private:
B b;
}
class B {
private:
C c;
}
class C {
// data
}
I understand I need every class's data to avoid being corrupted via a data race, however I would like to avoid throwing a ton of mutexes on every single method of every class. I'm not sure what the proper convention is.
You almost certainly don't want to try to make every class thread-safe, since doing so would end up being very inefficient (with lots of unnecessary locking and unlocking of mutexes for no benefit) and also prone to deadlocks (the more mutexes you have to lock at once, the more likely you are to have different threads locking sequences of mutexes in a different order, which is the entry condition for a deadlock and therefore your program freezing up on you).
What you want to do instead if figure out which data structures needs to be accessed by which thread(s). When designing your data structures, you want to try to design them in such a way that the amount of data shared between threads is as minimal as possible -- if you can reduce it to zero, then you don't need to do any serialization at all! (you probably won't manage that, but if you do a CSP/message-passing design you can get pretty close, in that the only mutexes you ever need to lock are the ones protecting your message-passing queues)
Keep in mind also that your mutexes are there not just to "protect the data" but also to allow a thread to make a series of changes appear to be atom from the viewpoint of the other threads that might access that data. That is, if your thread #1 needs to make changes to objects A, B, and C, and all three of those objects each have their own mutex, which thread #1 locks before modifying the object and then unlocks afterwards, you can still have a race condition, because thread #2 might "see" the update half-completed (i.e. thread #2 might examine the objects after you've updated A but before you've updated B and C). Therefore you usually need to push your mutexes up to a level where they cover all the objects you might need to change in one go -- in the ABC example case, that means you might want to have a single mutex that is used to serialize access to A, B, and C.
One way to approach it would be to start with just a single global mutex for your entire program -- anytime any thread needs to read or write any data structure that is accessible to other threads, that is the mutex it locks (and unlocks afterwards). That design probably won't be very efficient (since threads might spend a lot of time waiting for the mutex), but it will definitely not suffer from deadlock problems. Then once you have that working, you could look to see if that single mutex is actually a noticeable performance bottleneck for you -- if not, you're done, ship your program :) OTOH if it is a bottleneck, you can then analyze which of your data structures are logically independent from each other, and split your global mutex into two mutexes -- one to serialize access to subset A of the data structures, and another one to serialize access to subset B. (Note that the subsets don't need to be equal size -- subset B might contain just one particular data structure that is critical to performance) Repeat as necessary until either you're happy with performance, or your program starts to get too complicated or buggy (in which case you might want to dial the mutex-granularity back again a bit in order to regain your sanity).
I'm working with on real-time application divided in two parts (threads):
processing
graphics
the output of processing is an array of fixed size (of float) and to maintain a real-time performance I want to send such data to another thread that will draw, for example graphs, at its own pace.
I've looked into atomic and lock but I can't figure out how to make the application thread-safe given that the two processes are completely independent.
Sample code:
class A {
float data[n];
processData() {
data = ... ;
}
}
class B {
void draw() {
// requires data[] from class A
}
}
Both classes are initialized in the main thread and I've tried to define a float* pointer there and pass it to the other two threads, processing assigns it to data[] and graphics is able to read it but there's obviously errors when one is reading and the other is modifying it at the same time.
You could create a queue of your float values for the graphics output and a mutex.
Whenever the processing has generated some output, lock the common mutex, append the data to the queue, unlock the mutex.
On the other side, periodically lock the mutex from the graphics thread, see if there is new data to be displayed, if so then remove that data from the queue, temporarily copying it to a thread-local data buffer to ensure that the mutex is not locked while doing graphics output, and unlock the mutex right after the data is copied. Then display the graphics in that thread, using the local copy.
The simplest solution is to use an std::mutex to prevent both threads from accessing the data at the same time.
Of course, that means only 1 thread at a time can do something with the data. If that is a bottleneck (i.e. you want to generate new data while drawing previous data), consider double buffering. That way, both reading and writing can happen simultaneously. Note that you'll still need some sort of synchronization using e.g. a mutex to make sure the writer doesn't start writing into the buffer that's currently being used by the reader (or vice versa). You can improve on that by using triple buffering.
I have a singleton class implemented using Q_GLOBAL_STATIC that contains a data structure that has to be accessed from multiple threads, I implemented accessor functions in the class, that would lock a mutex before accessing the data, so that all accesses to the shared data are serialized.
The problem is that I want to use this data in a QAbstractTableModel, I can simply use the accessor functions I implemented and access one item at a time from my overridden data(), columnCount() and rowCount(). But I think this is insufficient, since between two subsequent calls to data() another thread may jump in and change the number of items for example (rowCount()), and the model's thread may end up accessing out of bounds data.
I think I need to lock the mutex before the very first call of columnCount() and rowCount() of the model reset, and unlock it only when all data is read into the model (after the last call to data()), is there a way to do so? or am I thinking the wrong way?
I thought of copying the shared data structure to a local one on model reset(and have the mutex locked only on the copy operation), and after that access the copied data safely, but isn't that an overkill? isn't there a more efficient solution?
In Qt's Model-View framework, the interface between QAbstractItemModel and QAbstractItemView is not threadsafe at all, it is designed to be used with only one thread, which must be the GUI thread, i.e. the main thread since view does painting on the GUI, which cannot be done securely in another thread than the main (GUI) thread.
Therefore a model must hold it's own data and synchronize it with real data. If your dataset is large, you can rely on fetchMore() to avoid copying the whole data in every model instance. See what is done in QtSql's sql models code. Then the lock-between-calls issue you raise is easier to solve.
You can even update the model in an event-driven way if the real data holder objects are able to emit signals connected to the model instance. Thanks to auto/queued signal connections, the model slots will execute in the main (GUI) thread and therefore won't need to be threadsafe with the QAbstractItemModel-QAbstractItemView interface.
In our application we deal with data that is processed in a worker thread and accessed in a display thread and we have a mutex that takes care of critical sections. Nothing special.
Now we thought about re-working our code where currently locking is done explicitely by the party holding and handling the data. We thought of a single entity that holds the data and only gives access to the data in a guarded fashion.
For this, we have a class called GuardedData. The caller can request such an object and should keep it only for a short time in local scope. As long as the object lives, it keeps the lock. As soon as the object is destroyed, the lock is released. The data access is coupled with the locking mechanism without any explicit extra work in the caller. The name of the class reminds the caller of the present guard.
template<typename T, typename Lockable>
class GuardedData {
GuardedData(T &d, Lockable &m) : data(d), guard(m) {}
boost::lock_guard<Lockable> guard;
T &data;
T &operator->() { return data; }
};
Again, a very simple concept. The operator-> mimics the semantics of STL iterators for access to the payload.
Now I wonder:
Is this approach well known?
Is there maybe a templated class like this already available, e.g. in the boost libraries?
I am asking because I think it is a fairly generic and usable concept. I could not find anything like it though.
Depending upon how this is used, you are almost guaranteed to end up with deadlocks at some point. If you want to operate on 2 pieces of data then you end up locking the mutex twice and deadlocking (unless each piece of data has its own mutex - which would also result in deadlock if the lock order is not consistent - you have no control over that with this scheme without making it really complicated). Unless you use a recursive mutex which may not be desired.
Also, how are your GuardedData objects passed around? boost::lock_guard is not copyable - it raises ownership issues on the mutex i.e. where & when it is released.
Its probably easier to copy parts of the data you need to the reader/writer threads as and when they need it, keeping the critical section short. The writer would similarly commit to the data model in one go.
Essentially your viewer thread gets a snapshot of the data it needs at a given time. This may even fit entirely in a cpu cache sitting near the core that is running the thread and never make it into RAM. The writer thread may modify the underlying data whilst the reader is dealing with it (but that should invalidate the view). However since the viewer has a copy it can continue on and provide a view of the data at the moment it was synchronized with the data.
The other option is to give the view a smart pointer to the data (which should be treated as immutable). If the writer wishes to modify the data, it copies it at that point, modifies the copy and when completes, switches the pointer to the data in the model. This would necessitate blocking all readers/writers whilst processing, unless there is only 1 writer. The next time the reader requests the data, it gets the fresh copy.
Well known, I'm not sure. However, I use a similar mechanism in Qt pretty often called a QMutexLocker. The distinction (a minor one, imho) is that you bind the data together with the mutex. A very similar mechanism to the one you've described is the norm for thread synchronization in C#.
Your approach is nice for guarding one data item at a time but gets cumbersome if you need to guard more than that. Additionally, it doesn't look like your design would stop me from creating this object in a shared place and accessing the data as often as I please, thinking that it's guarded perfectly fine, but in reality recursive access scenarios are not handled, nor are multi-threaded access scenarios if they occur in the same scope.
There seems to be to be a slight disconnect in the idea. Its use conveys to me that accessing the data is always made to be thread-safe because the data is guarded. Often, this isn't enough to ensure thread-safety. Order of operations on protected data often matters, so the locking is really scope-oriented, not data-oriented. You could get around this in your model by guarding a dummy object and wrapping your guard object in a temporary scope, but then why not just use one the existing mutex implementations?
Really, it's not a bad approach, but you need to make sure its intended use is understood.
What is the best way of performing the following in C++. Whilst my current method works I'm not sure it's the best way to go:
1) I have a master class that has some function in it
2) I have a thread that takes some instructions on a socket and then runs one of the functions in the master class
3) There are a number of threads that access various functions in the master class
I create the master class and then create instances of the thread classes from the master. The constructor for the thread class gets passed the "this" pointer for the master. I can then run functions from the master class inside the threads - i.e. I get a command to do something which runs a function in the master class from the thread. I have mutex's etc to prevent race problems.
Am I going about this the wrong way - It kinda seems like the thread classes should inherit the master class or another approach would be to not have separate thread classes but just have them as functions of the master class but that gets ugly.
Sounds good to me. In my servers, it is called 'SCB' - ServerControlBlock - and provides access to services like the IOCPbuffer/socket pools, logger, UI access for status/error messages and anything else that needs to be common to all the handler threads. Works fine and I don't see it as a hack.
I create the SCB, (and ensure in the ctor that all services accessed through it are started and ready for use), before creating the thread pool that uses the SCB - no nasty singletonny stuff.
Rgds,
Martin
Separate thread classes is pretty normal, especially if they have specific functionality. I wouldn't inherit from the main thread.
Passing the this pointer to threads is not, in itself, bad. What you do with it can be.
The this pointer is just like any other POD-ish data type. It's just a chunk of bits. The stuff that is in this might be more than PODs however, and passing what is in effect a pointer to it's members can be dangerous for all the usual reasons. Any time you share anything across threads, it introduces potential race conditions and deadlocks. The elementary means to resolve those conflicts is, of course, to introduce synchronization in the form of mutexes, semaphores, etc, but this can have the suprising effect of serializing your application.
Say you have one thread reading data from a socket and storing it to a synchronized command buffer, and another thread which reads from that command buffer. Both threads use the same mutex, which protects the buffer. All is well, right?
Well, maybe not. Your threads could become serialized if you're not very careful with how you lock the buffer. Presumably you created separate threads for the buffer-insert and buffer-remove codes so that they could run in parallel. But if you lock the buffer with each insert & each remove, then only one of those operations can be executing at a time. As long as your writing to the buffer, you can't read from it and vice versa.
You can try to fine-tune the locks so that they are as brief as possible, but so long as you have shared, synchronized data, you will have some degree of serialization.
Another approach is to hand data off to another thread explicitly, and remove as much data sharing as possible. Instead of writing to and reading from a buffer as in the above, for example, your socket code might create some kind of Command object on the heap (eg Command* cmd = new Command(...);) and pass that off to the other thread. (One way to do this in Windows is via the QueueUserAPC mechanism).
There are pros & cons to both approaches. The synchronization method has the benefit of being somewhat simpler to understand and implement at the surface, but the potential drawback of being much more difficult to debug if you mess something up. The hand-off method can make many of the problems inherent with synchronization impossible (thereby actually making it simpler), but it takes time to allocate memory on the heap.