I have a simple QT object. When I execute the code below the control is transfer to the QT object, but I would like to make the QT part work like a thread.
int main(int argc, char *args[])
{
gui *GUI;
//// before call
QApplication app(argc,args);
GUI = new gui();
GUI->show();
////i want to be able to do stuff here in parallel with the QT code.
// If I spawn a thead here or give a simple printf statement here
// or before call it executes only after GUI exits
return app.exec();
}
Make sure you not only create the thread but actually start it. Also, a printf() statement will execute before the GUI shows unless you forgot to terminate the string with a newline (\n).
Related
I am using pthread in my program. For creation using pthread_create(). Right after creation I am using pthread_setname_np() to set the created thread's name.
I am observing that the name I set takes a small time to reflect, initially the thread inherits the program name.
Any suggestions how I can set the thread name at the time I create the thread using pthread_create()? I researched a bit in the available pthread_attr() but did not find a function that helps.
A quick way to reproduce what I am observing, is as follows:
void * thread_loop_func(void *arg) {
// some code goes here
pthread_getname_np(pthread_self(), thread_name, sizeof(thread_name));
// Output to console the thread_name here
// some more code
}
int main() {
// some code
pthread_t test_thread;
pthread_create(&test_thread, &attr, thread_loop_func, &arg);
pthread_setname_np(test_thread, "THREAD-FOO");
// some more code, rest of pthread_join etc follows.
return 0;
}
Output:
<program_name>
<program_name>
THREAD-FOO
THREAD-FOO
....
I am looking for the first console output to reflect THREAD-FOO.
how I can set the thread name at the time I create the thread using pthread_create()?
That is not possible. Instead you can use a barrier or mutex to synchronize the child thread until it's ready to be run. Or you can set the thread name from inside the thread (if any other threads are not using it's name).
Do not to use pthread_setname_np. This is a nonstandard GNU extension. The _np suffix literally means "non-portable". Write portable code and instead use your own place where you store your thread names.
Instead of pthread_setname_np(3) you can use prctl(2) with PR_SET_NAME. The only limitation with this function is that you can only set the name of the calling process/thread. But since your example is doing exactly that, there should be no problem with this solution AND it's a portable standard API.
According to this, I'm using the system() (QProcess) function from inside my program to call the gpio program.
It works. But I've noticed I need to run my app two times, in fact it only works at the second time. It seems the call to gpio must be done in another process, as pointed here.
Should this problem be approached with QProcess::setupChildProcess()?
I extended QProcess overwriting setupChildProcess and then just instanciated SandboxProcess in the constructor of my app. Unfortunately, this didn't worked.
class SandboxProcess : public QProcess
{
protected:
void setupChildProcess();
};
void SandboxProcess::setupChildProcess()
{
QString program = "/usr/local/bin/gpio";
QStringList arguments;
arguments << "export" << QString::number(4) << "out";
start(program, arguments);
}
I guess QProcess::setupChildProcess() doesn't help because it's own process starts after the main app proccess. So the main app still fells like the export command was not executed.
At this point I see two options:
To make a ManagerApp, which call gpio (to do the exports) and then call (another) MyApp which will actually access the exported devices.
Use the gpio app directly and listen to their stdout via signal/slot, using QProcess.
I'm trying to develop a GDB python extension that defines a command that launches a new thread, in which the user can inspect an arbitrary type of variables. The skeleton of my python extension is this:
import gdb
import threading
def plot_thread():
import time
while True:
print('Placeholder for a window event loop.')
time.sleep(1)
pass
pass
class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
self.dont_repeat()
pass
def invoke(self, arg, from_tty):
plot_thread_instance=threading.Thread(target=plot_thread)
plot_thread_instance.daemon=True
plot_thread_instance.start()
pass
pass
PlotterCommand()
As can be seen, I define a plot command here. When I try to debug the following program, GDB will hang if I:
Put a breakpoint anywhere inside the procedure() thread (say, line 9, inside the while loop).
Run the command plot after gdb hits the breakpoint.
Run continue after that.
#include <iostream>
#include <thread>
using namespace std;
void procedure() {
cout << "before loop"<<endl;
while(1) {
cout << "loop iteration"<<endl;
}
}
int main() {
thread t(procedure);
t.join();
return 0;
}
The strangest thing is that, if I change this code to call procedure() without launching a thread, GDB never hangs (and the placeholder messages are still printed as I expect).
So far, I've tried to run this procedure with GDB versions 7.5.1 and 7.10, but I always experience the same behavior.
What am I doing wrong? Aren't daemon threads not supported by GDB? That doesn't seem to be in accordance with what the section 23.2.2.1 of the documentation is suggesting: GDB may not be thread safe, but I don't think it should hang after launching such a silly daemon thread.
From this blog post:
GDB uses this function (sigsuspend, the function where GDB hangs) to wait for new events from the application execution: when something occurs in the debuggee (see how debuggers work), the kernel will inform GDB of it by sending a SIGCHLD signal. When it's received, GDB awakes and check what happened.
However, the signal is delivered to GDB process, but not necessarily to its main thread. And it practise, it occurs often that it's delivered to the second thread, who doesn't care about it (that's the default behavior), and continues its life as if nothing occurred.
The solution is to configure the thread signal handling behavior, so that only the GDB main thread gets notified by these signals:
import gdb
import threading
import pysigset, signal # Import these packages!
def plot_thread():
import time
while True:
print('Placeholder for a window event loop.')
time.sleep(1)
pass
pass
class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
self.dont_repeat()
pass
def invoke(self, arg, from_tty):
with pysigset.suspended_signals(signal.SIGCHLD): # Disable signals here!
plot_thread_instance=threading.Thread(target=plot_thread)
plot_thread_instance.daemon=True
plot_thread_instance.start()
pass
pass
pass
PlotterCommand()
The pysigset package is required, and can be installed from pip (sudo pip install pysigset).
If I compile and run the code as-is, the process will run with 1 thread. If I uncomment the commented out section and then compile and run it, it runs with 2 threads.
I am compiling the code with this command:
g++ pkg-config gtkmm-2.4 --cflags --libs test.cpp
When the program is running I can check how many threads are created with:
ps -mC a.out
If I look at the second thread in ddd, I can see that it is running g_main_loop_run. This confuses me:
What is the purpose of this thread?
Why does adding a toolbar button create a new thread?
I thought g_main_loop_run() should only ever run in one thread (unless you use the GDK_THREADS_ENTER/GDK_THREADS_LEAVE macros). Since I am running Gtk::Main::Run() in my main thread am breaking the rules?
Thanks in advance for any help. It's driving me crazy.
#include <gtkmm.h>
bool OnDeleteEvent(GdkEventAny* PtrGdkEventAny)
{
Gtk::Main::quit();
return(true);
}
void OnExecuteButtonClicked()
{
}
int main(int argc, char *argv[])
{
new Gtk::Main(0, NULL);
Gtk::Window *ptrWindow = new Gtk::Window;
ptrWindow->signal_delete_event().connect(sigc::ptr_fun(&OnDeleteEvent));
/*
Gtk::Toolbar *ptrToolBar = manage(new Gtk::Toolbar);
Gtk::ToolButton *ptrToolButton;
ptrToolButton = manage( new Gtk::ToolButton(Gtk::Stock::EXECUTE));
ptrToolBar->append(*ptrToolButton, sigc::ptr_fun(&OnExecuteButtonClicked));
ptrWindow->add(*ptrToolBar);
*/
ptrWindow->show_all();
Gtk::Main::run();
return (0);
}
Sometimes GThreads are created when you use functions that rely on async behaviour. These usually create a GTask internally (with g_task_run_in_thread and friends) and run the synchronous version in a seperate thread (except for those being nativly async or async-able, those usually won't spawn another thread). Usually this is IO (i.e. GtkBuilder), Socket and IPC (dbus) related - so mostly glib stuff.
There might also be occasions which I am not aware of, that will spawn additional threads, the mainloop itself is strictly single threaded.
So in your case I can only think of two thing that could trigger this: The Stock image that is loaded from your local disk or the styling information of your theme.
I am creating a music library app using Qt( C++). It involves a method that does the following jobs in the given sequence-
List N audio files by recursively traversing a directory.
Read each and every file to collect ID3 tags.
Extract artwork images from the files.
Save the ID3 tags in the database.
The above set of tasks are extremely resource intensive. For N ~ 1000, it takes around a minute and half to complete the tasks and during the course of execution of this sequence, the GUI freezes up and doesn't respond well as I currently use no other threads.
I have seen a few examples of Qt threading and they more or less tell how to do things in parallel as expected but in those examples, achieving parallelism or concurrency is a requirement as they don't have any other options. But in case of my app, it's a choice whether I use multiple threads or not. The goal is to make sure the GUI stays responsive and interactive during the execution of the resource intensive task.I would really appreciate any expert advice may be with a code template or example in Qt to perform the resource intensive task in a different thread.
Code in main thread-
QStringList files;
QString status;
createLibrary(files, status); //To be done in a different thread
if(status == "complete"){
//do something
}
Thanks a lot your time!
You could use the QtConcurrent module.
Use QtConcurrent::map() to iterate over the list of files and call a method in separate thread:
QFuture<void> result = QtConcurrent::map(files, createLibrary);
QFutureWatcher will send a signal when the processing is done:
QFutureWatcher<void> watcher;
connect(&watcher, SIGNAL(finished()),
this, SLOT(processingFinished()));
// Start the computation.
QFuture<void> result = QtConcurrent::map(files, createLibrary);
watcher.setFuture(result);
BTW because of a lot of bad files in the wild, the music player Amarok decided to put the id3 tag scanner in a separate process. See here for more informations.
My best advice would be to create a subclass QThread. Pass this subclass a pointer to the directories and give it a pointer to a valid (non-null) view that you want to update in the following way:
header.h
class SearchAndUpdate : public QThread
{
Q_OBJECT
public:
SearchAndUpdate(QStringList *files, QWidget *widget);
//The QWidget can be replaced with a Layout or a MainWindow or whatever portion
//of your GUI that is updated by the thread. It's not a real awesome move to
//update your GUI from a background thread, so connect to the QThread::finished()
//signal to perform your updates. I just put it in because it can be done.
~SearchAndUpdate();
QMutex mutex;
QStringList *f;
QWidget *w;
bool running;
private:
virtual void run();
};
Then in your implementation for that thread do this:
thread.cpp
SearchAndUpdate(QStringList *files, QWidget *widget){
this->f=files;
this->w=widget;
}
void SearchAndUpdate::run(){
this->running=true;
mutex.lock();
//here is where you do all the work
//create a massive QStringList iterator
//whatever you need to complete your 4 steps.
//you can even try to update your QWidget *w pointer
//although some window managers will yell at you
mutex.unlock();
this->running=false;
this->deleteLater();
}
Then in your GUI thread maintain the valid pointers QStringList *files and SearchAndUpdate *search, then do something like this:
files = new QStringList();
files->append("path/to/file1");
...
files->append("path/to/fileN");
search = new SearchAndUpdate(files,this->ui->qwidgetToUpdate);
connect(search,SIGNAL(finished()),this,SLOT(threadFinished()));
search->start();
...
void threadFinished(){
//update the GUI here and no one will be mad
}