C++11: Ensure that GUI calls are made from the main thread - c++

I have a multithreaded GUI program where I need to queue events that are called from another thread. I would like to make sure that GUI calls are primarily made from the main thread. Does the call std::this_thread::get_id() preserve its value throughout the whole application?
I'm planning something like this:
GuiElement
{
std::thread::id main_thread_id;
public:
GuiElement()
{
main_thread_id = std::this_thread::get_id();
}
void thread_check()
{
if(std::this_thread::get_id() != this->main_thread_id)
{
throw std::runtime_error("You can't call this from a different thread");
}
}
void remove_element(const std::string& element_name)
{
this->thread_check();
//do stuff
}
};
Is this the right thing to do? Or is there something better to achieve this functionality?
Although unlikely, but I'm worried that a thread id might change for some reason. Can this happen?

for your question about the possibility of thread changing the id, you can relay on the that as long as the thread is running, it will be safe to assume that the thread id will not change.
take a look here std::thread::id, it states that the class purpose is to be used key in associative containers.

Related

Running a task in a separate thread which shold be able to stop on request

I am trying to design an infinite (or a user-defined length) loop that would be independent of my GUI process. I know how to start that loop in a separate thread, so the GUI process is not blocked. However, I would like to have a possibility to interrupt the loop at a press of a button. The complete scenario may look like this:
GUI::startButton->myClass::runLoop... ---> starts a loop in a new thread
GUI::stopButton->myClass::terminateLoop ---> should be able to interrupt the started loop
The problem I have is figuring out how to provide the stop functionality. I am sure there is a way to achieve this in C++. I was looking at a number of multithreading related posts and articles, as well as some lectures on how to use async and futures. Most of the examples did not fit my intended use and/or were too complex for my current state of skills.
Example:
GUIClass.cpp
MyClass *myClass = new MyClass;
void MyWidget::on_pushButton_start_clicked()
{
myClass->start().detach();
}
void MyWidget::on_pushButton_stop_clicked()
{
myClass->stop(); // TBD: how to implement the stop functionality?
}
MyClass.cpp
std::thread MyClass::start()
{
return std::thread(&MyClass::runLoop, this);
}
void MyClass::runLoop()
{
for(int i = 0; i < 999999; i++)
{
// do some work
}
}
As far as i know, there is no standard way to terminate a STL thread. And even if possible, this is not advisable since it can leave your application in an undefined state.
It would be better to add a check to your MyClass::runLoop method that stops execution in a controlled way as soon as an external condition is fulfilled. This might, for example, be a control variable like this:
std::thread MyClass::start()
{
_threadRunning = true;
if(_thread.joinable() == true) // If thr thread is joinable...
{
// Join before (re)starting the thread
_thread.join();
}
_thread = std::thread(&MyClass::runLoop, this);
return _thread;
}
void MyClass::runLoop()
{
for(int i = 0; i < MAX_ITERATION_COUNT; i++)
{
if(_threadRunning == false) { break; }
// do some work
}
}
Then you can end the thread with:
void MyClass::stopLoop()
{
_threadRunning = false;
}
_threadRunning would here be a member variable of type bool or, if your architecture for some reason has non-atomic bools, std::atomic<bool>.
With x86, x86_64, ARM and ARM64, however, you should be fine without atomic bools. It, however is advised to use them. Also to hint at the fact that the variable is used in a multithreading context.
Possible MyClass.h:
MyClass
{
public:
MyClass() : _threadRunning(false) {}
std::thread start();
std::thread runLoop();
std::thread stopLoop();
private:
std::thread _thread;
std::atomic<bool> _threadRunning;
}
It might be important to note that, depending on the code in your loop, it might take a while before the thread really stops.
Therefore it might be wise to std::thread::join the thread before restarting it, to make sure only one thread runs at a time.

How to keep std::thread from freezing GUI in QT?

I am working on a project where I will be ingesting multiple binary files, decode them, and convert their data into a CSV. I figured the quickest way to do this would be to thread the work. Simply load the files into a queue, have the threads grab a file, work on it, convert it, output it, and then die.
What I wrote actually works great, however, I cannot figure out how to get the GUI to be responsive as I have a progress bar that I would like to update or simply have the user move the GUI to a corner while it processes the data. And I believe this is because std::thread is just hanging up the GUI.
In my code I have the following function once a button is pressed to execute:
void MyExtractor::on_Execute_clicked()
{
QStringList binary = tlmFiles.entryList(QStringList() << "*.bin",QDir::Files);
queue.clear();
threadPool.clear();
if(binary.size() != 0)
{
foreach(QString filename, binary)
{
queue.emplace_back(inputDir + '/' + filename);
}
for (unsigned int i = 0; i < std::thread::hardware_concurrency(); ++i)
{
threadPool.emplace_back(&MyExtractor::initThread,this,std::ref(queue),std::ref(mut));
}
}
else
{
message.setText("No binary files found! Please select another folder!");
message.exec();
}
for (auto &&e : threadPool)
{
e.join();
}
}
And initThread looks like this:
void MyExtractor::initThread(std::deque<QString> &queue, std::mutex &mutex)
{
QString file;
QString toOutput = outputDir;
while(queue.size() > 0)
{
{
std::lock_guard<std::mutex> lock(mutex);
if(!queue.empty())
{
file = queue.front();
queue.pop_front();
}
}
BitExtract *bitExtractor = new BitExtract();
if(file.size() != 0)
{
bitExtractor->extract(file,toOutput);
}
delete bitExtractor;
}
}
I have been reading about QThreads. And from what I think I have been reading, it seems I need to create a separate thread to watch the work, and the other thread to watch the GUI? I am not sure if I have worded that correctly. However, I am not even sure how to go about that since I am using a std::thread to do the conversion, and I am not sure how well QThread will play with this. Any suggestions?
EDIT: I should make it clear that threadPool is a std::vector<std::thread>
As noted by #drescherjm, your problem is here:
for (auto &&e : threadPool)
{
e.join();
}
join() won't return until the thread has completed, which means your GUI thread will be blocked inside that for-loop until all threads have exited, which is what you want to avoid. (it's always desirable for any function in the main/Qt/GUI thread to return as quickly as possible, so that Qt's GUI event loop can remain responsive)
Avoiding that is fairly straightforward -- instead of calling join() right after the threads have been spawned, you should only call join() on a thread after the thread has notified you that it has completed its work and is about to exit. That way join() will never take more than a few milliseconds to return.
As for how to get a std::thread to notify your main/GUI thread that it has finished its task, one simple way to do it is to have your std::thread call QApplication::postEvent() just before it exits, and override the event(QEvent *) virtual method on (whatever object you passed in as the first argument to postEvent()) to handle the posted event-object (note that you can make your own subclass of QEvent that contains whatever data you want to send to the GUI thread) by calling join() on the std::thread, plus whatever cleanup and result-handling code you need to execute after a thread has returned its result.

std::async analogue for specified thread

I need to work with several objects, where each operation may take a lot of time.
The processing could not be placed in a GUI (main) thread, where I start it.
I need to make all the communications with some objects on asynchronous operations, something similar to std::async with std::future or QtConcurrent::run() in my main framework (Qt 5), with QFuture, etc., but it doesn't provide thread selection. I need to work with a selected object (objects == devices) in only one additional thread always,
because:
I need to make a universal solution and don't want to make each class thread-safe
For example, even if make a thread-safe container for QSerialPort, Serial port in Qt cannot be accessed in more than one thread:
Note: The serial port is always opened with exclusive access (that is, no other process or thread can access an already opened serial port).
Usually a communication with a device consists of transmit a command and receive an answer. I want to process each Answer exactly in the place where Request was sent and don't want to use event-driven-only logic.
So, my question.
How can the function be implemented?
MyFuture<T> fut = myAsyncStart(func, &specificLiveThread);
It is necessary that one live thread can be passed many times.
Let me answer without referencing to Qt library since I don't know its threading API.
In C++11 standard library there is no straightforward way to reuse created thread. Thread executes single function and can be only joined or detachted. However, you can implement it with producer-consumer pattern. The consumer thread needs to execute tasks (represented as std::function objects for instance) which are placed in queue by producer thread. So if I am correct you need a single threaded thread pool.
I can recommend my C++14 implementation of thread pools as tasks queues. It isn't commonly used (yet!) but it is covered with unit tests and checked with thread sanitizer multiple times. The documentation is sparse but feel free to ask anything in github issues!
Library repository: https://github.com/Ravirael/concurrentpp
And your use case:
#include <task_queues.hpp>
int main() {
// The single threaded task queue object - creates one additional thread.
concurrent::n_threaded_fifo_task_queue queue(1);
// Add tasks to queue, task is executed in created thread.
std::future<int> future_result = queue.push_with_result([] { return 4; });
// Blocks until task is completed.
int result = future_result.get();
// Executes task on the same thread as before.
std::future<int> second_future_result = queue.push_with_result([] { return 4; });
}
If you want to follow the Active Object approach here is an example using templates:
The WorkPackage and it's interface are just for storing functions of different return type in a vector (see later in the ActiveObject::async member function):
class IWorkPackage {
public:
virtual void execute() = 0;
virtual ~IWorkPackage() {
}
};
template <typename R>
class WorkPackage : public IWorkPackage{
private:
std::packaged_task<R()> task;
public:
WorkPackage(std::packaged_task<R()> t) : task(std::move(t)) {
}
void execute() final {
task();
}
std::future<R> get_future() {
return task.get_future();
}
};
Here's the ActiveObject class which expects your devices as a template. Furthermore it has a vector to store the method requests of the device and a thread to execute those methods one after another. Finally the async function is used to request a method call from the device:
template <typename Device>
class ActiveObject {
private:
Device servant;
std::thread worker;
std::vector<std::unique_ptr<IWorkPackage>> work_queue;
std::atomic<bool> done;
std::mutex queue_mutex;
std::condition_variable cv;
void worker_thread() {
while(done.load() == false) {
std::unique_ptr<IWorkPackage> wp;
{
std::unique_lock<std::mutex> lck {queue_mutex};
cv.wait(lck, [this] {return !work_queue.empty() || done.load() == true;});
if(done.load() == true) continue;
wp = std::move(work_queue.back());
work_queue.pop_back();
}
if(wp) wp->execute();
}
}
public:
ActiveObject(): done(false) {
worker = std::thread {&ActiveObject::worker_thread, this};
}
~ActiveObject() {
{
std::unique_lock<std::mutex> lck{queue_mutex};
done.store(true);
}
cv.notify_one();
worker.join();
}
template<typename R, typename ...Args, typename ...Params>
std::future<R> async(R (Device::*function)(Params...), Args... args) {
std::unique_ptr<WorkPackage<R>> wp {new WorkPackage<R> {std::packaged_task<R()> { std::bind(function, &servant, args...) }}};
std::future<R> fut = wp->get_future();
{
std::unique_lock<std::mutex> lck{queue_mutex};
work_queue.push_back(std::move(wp));
}
cv.notify_one();
return fut;
}
// In case you want to call some functions directly on the device
Device* operator->() {
return &servant;
}
};
You can use it as follows:
ActiveObject<QSerialPort> ao_serial_port;
// direct call:
ao_serial_port->setReadBufferSize(size);
//async call:
std::future<void> buf_future = ao_serial_port.async(&QSerialPort::setReadBufferSize, size);
std::future<Parity> parity_future = ao_serial_port.async(&QSerialPort::parity);
// Maybe do some other work here
buf_future.get(); // wait until calculations are ready
Parity p = parity_future.get(); // blocks if result not ready yet, i.e. if method has not finished execution yet
EDIT to answer the question in the comments: The AO is mainly a concurrency pattern for multiple reader/writer. As always, its use depends on the situation. And so this pattern is commonly used in distributed systems/network applications, for example when multiple clients request a service from a server. The clients benefit from the AO pattern as they are not blocked, when waiting for the server to answer.
One reason why this pattern is not used so often in fields other then network apps might be the thread overhead. When creating a thread for every active object results in a lot of threads and thus thread contention if the number of CPUs is low and many active objects are used at once.
I can only guess why people think it is a strange issue: As you already found out it does require some additional programming. Maybe that's the reason but I'm not sure.
But I think the pattern is also very useful for other reasons and uses. As for your example, where the main thread (and also other background threads) require a service from singletons, for example some devices or hardware interfaces, which are only availabale in a low number, slow in their computations and require concurrent access, without being blocked waiting for a result.
It's Qt. It's signal-slot mechanism is thread-aware. On your secondary (non-GUI) thread, create a QObject-derived class with an execute slot. Signals connected to this slot will marshal the event to that thread.
Note that this QObject can't be a child of a GUI object, since children need to live in their parents thread, and this object explicitly does not live in the GUI thread.
You can handle the result using existing std::promise logic, just like std::future does.

How to access QWidget from other threads

I have
struct MyWidget : QWidget {
// non-GUI related stuff:
int data;
int doSth();
};
I need to access a MyWidget instance from another thread (i.e. not the main thread). Is there any way to do that safely? I understand that I cannot access GUI related functions because some backends (e.g. MacOSX/Cocoa) don't support that. However, I only need to access data or doSth() in this example. But from what I have understand, there is simply no way to guarantee the lifetime of the object - i.e. if the parent window with that widget closes, the MyWidget instance gets deleted.
Or is there a way to guarantee the lifetime? I guess QSharedPointer doesn't work because the QWidget does its lifetime handling internally, depending on the parent widget. QPointer of course also doesn't help because it is only weak and there is no locking mechanism.
My current workaround is basically:
int widget_doSth(QPointer<MyWidget> w) {
int ret = -1;
execInMainThread_sync([&]() {
if(w)
ret = w->doSth();
});
return ret;
}
(execInMainThread_sync works by using QMetaMethod::invoke to call a method in the main thread.)
However, that workaround doesn't work anymore for some specific reason (I will explain later why, but that doesn't matter here). Basically, I am not able to execute something in the main thread at that point (for some complicated deadlock reasons).
Another workaround I'm currently thinking about is to add a global mutex which will guard the MyWidget destructor, and in the destructor, I'm cleaning up other weak references to the MyWidget. Then, elsewhere, when I need to ensure the lifetime, I just lock that mutex.
The reason why my current workaround doesn't work anymore (and that is still a simplified version of the real situation):
In MyWidget, the data is actually a PyObject*.
In the main thread, some Python code gets called. (It's not really possible to avoid any Python code calls at all in the main thread in my app.) That Python code ends up doing some import, which is guarded by some Python-import-mutex (Python doesn't allow parallel imports.)
In some other Python thread, some other import is called. That import now locks the Python-import-mutex. And while it's doing its thing, it does some GC cleanup at some point. That GC cleanup calls the traverse function of some object which holds that MyWidget. Thus, it must access the MyWidget. However, execInMainThread_sync (or equivalently working solutions) will deadlock because the main thread currently waits for the Python-import-lock.
Note: The Python global interpreter lock is not really the problem. Of course it gets unlocked before any execInMainThread_sync call. However, I cannot really check for any other potential Python/whatever locks. Esp. I am not allowed to just unlock the Python-import-lock -- it's there for a reason.
One solution you might think of is to really just avoid any Python code at all in the main thread. But that has a lot of drawbacks, e.g. it will be slow, complicated and ugly (the GUI basically only shows data from Python, so there need to be a huge proxy/wrapper around it all). And I think I still need to wait at some points for the Python data, so I just introduce the possible deadlock-situation at some other point.
Also, all the problems would just go away if I could access MyWidget safely from another thread. Introducing a global mutex is the much cleaner and shorter solution, compared to above.
You can use the signal/slot mechanism, but it can be tedious, if the number of GUI controls is large. I'd recommend a single signal and slot to control the gui. Send over a struct with all the info needed for updating the GUI.
void SomeWidget::updateGUISlot(struct Info const& info)
{
firstControl->setText(info.text);
secondControl->setValue(info.value);
}
You don't need to worry about emitting signals, if the recipient is deleted. This detail is handled by Qt. Alternatively, you can wait for your threads to exit, after exiting the GUI threads event loop. You'll need to register the struct with Qt.
EDIT:
From what I've read from your extended question, you're problems are related to communication between threads. Try pipes, (POSIX) message queues, sockets or POSIX signals instead of Qt signals for inter-thread communication.
Personally I don't like designs where GUI stuff (ie: A widget) has non-GUI related stuff... I think you should separate these two from each other. Qt needs to keep the GUI objects always on the main thread, but anything else (QObject derived) can be moved to a thread (QObject::moveToThread).
It seems that what you're explaining has nothing at all to do with widgets, Qt, or anything like that. It's a problem inherent to Python and its threading and the lock structure that doesn't make sense if you're multithreading. Python basically presumes that any object can be accessed from any thread. You'd have the same problem using any other toolkit. There may be a way of telling Python not to do that - I don't know enough about the cpython implementation's details, but that's where you'd need to look.
That GC cleanup calls the traverse function of some object which holds that MyWidget
That's your problem. You must ensure that such cross-thread GC cleanup can't happen. I have no idea how you'd go about it :(
My worry is that you've quietly and subtly shot yourself in the foot by using Python, in spite of everyone claiming that only C/C++ lets you do it at such a grand scale.
My solution:
struct MyWidget : QWidget {
// some non-GUI related stuff:
int someData;
virtual void doSth();
// We reset that in the destructor. When you hold its mutex-lock,
// the ref is either NULL or a valid pointer to this MyWidget.
struct LockedRef {
boost::mutex mutex;
MyWidget* ptr;
LockedRef(MyWidget& w) : ptr(&w) {}
void reset() {
boost::mutex::scoped_lock lock(mutex);
ptr = NULL;
}
};
boost::shared_ptr<LockedRef> selfRef;
struct WeakRef;
struct ScopedRef {
boost::shared_ptr<LockedRef> _ref;
MyWidget* ptr;
bool lock;
ScopedRef(WeakRef& ref);
~ScopedRef();
operator bool() { return ptr; }
MyWidget* operator->() { return ptr; }
};
struct WeakRef {
typedef boost::weak_ptr<LockedRef> Ref;
Ref ref;
WeakRef() {}
WeakRef(MyWidget& w) { ref = w.selfRef; }
ScopedRef scoped() { return ScopedRef(*this); }
};
MyWidget();
~MyWidget();
};
MyWidget::ScopedRef::ScopedRef(WeakRef& ref) : ptr(NULL), lock(true) {
_ref = ref.ref.lock();
if(_ref) {
lock = (QThread::currentThread() == qApp->thread());
if(lock) _ref->mutex.lock();
ptr = _ref->ptr;
}
}
MyWidget::ScopedRef::~ScopedRef() {
if(_ref && lock)
_ref->mutex.unlock();
}
MyWidget::~QtBaseWidget() {
selfRef->reset();
selfRef.reset();
}
MyWidget::MyWidget() {
selfRef = boost::shared_ptr<LockedRef>(new LockedRef(*this));
}
Now, everywhere I need to pass around a MyWidget pointer, I'm using:
MyWidget::WeakRef widget;
And I can use it from another thread like this:
MyWidget::ScopedRef widgetRef(widget);
if(widgetRef)
widgetRef->doSth();
This is safe. As long as ScopedRef exists, MyWidget cannot be deleted. It will block in its destructor. Or it is already deleted and ScopedRef::ptr == NULL.

How can I protect a QThread function so it will not be called again until finished its previous work?

I'm using a QThread and inside its run method I have a timer invoking a function that performs some heavy actions that take some time. Usually more than the interval that triggers the timer (but not always).
What I need is to protect this method so it can be invoked only if it has completed its previous job.
Here is the code:
NotificationThread::NotificationThread(QObject *parent)
: QThread(parent),
bWorking(false),
m_timerInterval(0)
{
}
NotificationThread::~NotificationThread()
{
;
}
void NotificationThread::fire()
{
if (!bWorking)
{
m_mutex.lock(); // <-- This is not protection the GetUpdateTime method from invoking over and over.
bWorking = true;
int size = groupsMarkedForUpdate.size();
if (MyApp::getInstance()->GetUpdateTime(batchVectorResult))
{
bWorking = false;
emit UpdateNotifications();
}
m_mutex.unlock();
}
}
void NotificationThread::run()
{
m_NotificationTimer = new QTimer();
connect(m_NotificationTimer,
SIGNAL(timeout()),
this,
SLOT(fire(),
Qt::DirectConnection));
int interval = val.toInt();
m_NotificationTimer->setInterval(3000);
m_NotificationTimer->start();
QThread::exec();
}
// This method is invoked from the main class
void NotificationThread::Execute(const QStringList batchReqList)
{
m_batchReqList = batchReqList;
start();
}
You could always have a thread that needs to run the method connected to an onDone signal that alerts all subscribers that it is complete. Then you should not run into the problems associated with double lock check and memory reordering. Maintain the run state in each thread.
I'm assuming you want to protect your thread from calls from another thread. Am I right? If yes, then..
This is what QMutex is for. QMutex gives you an interface to "lock" the thread until it is "unlocked", thus serializing access to the thread. You can choose to unlock the thread until it is done doing its work. But use it at your own risk. QMutex presents its own problems when used incorrectly. Refer to the documentation for more information on this.
But there are many more ways to solve your problem, like for example, #Beached suggests a simpler way to solve the problem; your instance of QThread would emit a signal if it's done. Or better yet, make a bool isDone inside your thread which would then be true if it's done, or false if it's not. If ever it's true then it's safe to call the method. But make sure you do not manipulate isDone outside the thread that owns it. I suggest you only manipulate isDone inside your QThread.
Here's the class documentation: link
LOL, I seriously misinterpreted your question. Sorry. It seems you've already done my second suggestion with bWorking.