I've a thread that read datas
class MyThread: QThread
{
...
}
void MyThread::run ()
{
uint8_t* buffer; // in my real code, it's a ring, so there is not read during write
// ...
while (true)
{
if (isInterruptionRequested())
return;
USB_READ(buffer);
emit newData(buffer);
}
}
In my UI Class I have:
connect(this, &UIClass::newData, m_thread, &MyThread::newData);
// ...
void newData(uint8_t* data)
{
// Process data
}
void UIClass::closeEvent(QCloseEvent *event)
{
disconnect(this, &UIClass::newData, m_thread, &MyThread::newData);
m_thread->requestInterruption();
m_thread->wait();
}
The problem with that if, when I click on "close", the thread is destroyed that cause the pointer data to be invalid. The signal newData is sometimes called that cause my function to work with invalid pointer and segfault. How to be sure that is not gonna happend ?
For now, I use a std::this_thread::sleep_for() with an arbitrary delay, it works, but I not find this very beautiful
That I have in my mind :
- disconnect the signal
- wait for the pendings signals to be executed
- exit
The problem is that you send a pointer from one thread to another without ensuring the pointer stays valid.
You have multiple choices to solve this. Either use QSharedPointer (or similar utilities from the stl) to hold your data, doing so will ensure your pointer will remain valid (or provide you a way to detect when the pointer becomes invalid if you also use QWeakPointer). Or you could make use of QByteArray to pass the data, but this will make a copy.
Example 1
void MyThread::run ()
{
QSharedPointer<uint8_t> buffer (new uint8_t[N]()); // Do not delete[], QSharedPointer will handle it
...
emit newData(buffer);
}
void newData(QSharedPointer<uint8_t> data)
{
// data is always valid
// Process data
}
Example 2
void MyThread::run ()
{
QSharedPointer<uint8_t> buffer (new uint8_t[N]());
...
emit newData(buffer);
}
void newData(QWeakPointer<uint8_t> data)
{
// data might not be valid but we can check
QSharedPointer<uint8_t> buffer (data);
if (!buffer)
return;
// Process data
}
Example 3
void MyThread::run ()
{
uint8_t[N] buffer;
...
emit newData(QByteArray(buffer, size));
}
void newData(QByteArray data)
{
// data is valid
// Process data
}
All you need to do is for the thread to outlive the user interface. That's rather easy:
class MyThread : public QThread
{
Q_OBJECT
RingBuffer buffer;
public:
void run() override;
~MyThread() {
requestInterruption();
quit();
wait();
}
Q_SIGNAL newData(RingBuffer *);
};
int main(int argc, char **argv) {
QApplication app{argc, argv};
MyThread thread;
thread.start();
UIClass ui;
connect(&thread, &MyThread::newData, &ui, &UIClass::newData);
return app.exec();
}
Related
I have a program that takes a long action, I run this function on a different thread. Periodically I need to update the information for the user, so I send a signal to the GUI thread. But sometimes I need the user to make a choice, I need to display the QDialog on the GUI thread and pause the slow thread while the user selects an option, and when the user completes the selection, return the value to the slow thread and continue it
it should look something like this:
But I don’t know how to stop and continue the thread and whether it should be done this way.
Header:
class Example:public QObject
{
//...
Q_OBJECT
void mainLoop();
Example();
signals:
void updateGUI(const QString &message);
void sendQuestion(const QString &message);
void continueMainLoop(const QString &answer);
private slots:
void updatuGUIslot(const QString &message);
void showQuestionDialog(const QString &message);
};
Source:
Example::Example()
{
connect(this,&Example::updateGUI,this,&Example::updatuGUIslot);
connect(this,&Example::sendQuestion,this,&Example::showQuestionDialog);
std::thread t(&Example::mainLoop,this);
t.detach();
// in the project it is not in the constructor
}
void Example::mainLoop()
{
while(some condition1)
{
// slow action
if(some condition2)
emit updateGUI("message");
if(some condition3)
{
QString result;
ThreadPtr th = this_thread(); // pseudocode
connect(this,&Example::continueMainLoop,this,[&](const QString &answer)
{
result = answer;
th.continue(); // pseudocode
});
emit sendQuestion("question");
th.wait(); // pseudocode
}
// slow action
}
}
void Example::showQuestionDialog(const QString &message)
{
// show dialog with question
emit continueMainLoop("answer");
}
void Example::updatuGUIslot(const QString &message)
{
// update GUI
}
you need to invoke the method with BlockingQueuedConnection before condition3 for checking which option that selected by the user.
bool updateGui ;
QMetaObject::invokeMethod(this, "showDialog",Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, updateGui));
if(updateGui)
{
//update GUI
}
I want to wirte a funtion CH1_Hard_Soft to process data, which accepts two arguments from two different function.
double MainWindow::getdata_CH1(double time)
{
...
double CH1_data=0;
switch (CH1.Source) {
case 0: //software-hard
CH1_data = CH1_Hard_Soft(time);
....
}
The function CH1_Hard_Soft need to accept an argument time from getdata_CH1 and accept a QVector from other thread. And the function CH1_Hard_Soft will process these data and then return a QVector to getdata_CH1(double time). I don't know how to do this. Please give me some suggestions on how to do this.THANKS!!!
You can use a Function Object: create a new class with two attributes (one per parameter). Create setter for each parameter (or redefine the operator () to be closer to the behavior of a real function).
Each setter should check if the others are setted also. In that case, call you algorithm and send the result with a signal.
For example:
A simple worker executed in another thread. It will send fake data after 3 seconds
class Worker: public QObject
{
Q_OBJECT
public:
Worker(): QObject()
{
}
void timerEvent(QTimerEvent* ev)
{
qDebug() << Q_FUNC_INFO;
emit getVector(QVector<int>() << 2 << 4 << 6 << 8);
killTimer(timerId);
}
public slots:
void run()
{
timerId = startTimer(3000);
}
signals:
void getVector(QVector<int> const& vec);
private:
int timerId;
};
The Function Object: it will accept two param (a double and a vector)
// For convenience. Define a value and a flag to check if the value is well set
template<typename T> struct Param
{
T value;
bool isInit;
Param(): isInit(false)
{}
void setValue(T const& v)
{
value = v;
isInit = true;
}
};
// The processor
class Processor: public QObject
{
Q_OBJECT
public:
Processor(QObject* parent=nullptr): QObject(parent)
{}
void operator()(QVector<int> const& vector)
{
values.setValue(vector);
if (time.isInit)
process();
}
void operator()(double t)
{
time.setValue(t);
if (values.isInit)
process();
}
signals:
void done(double result);
private:
// Will be called as soon as all the parameters are set
void process()
{
// DO something
qDebug() << Q_FUNC_INFO;
emit done(time.value * values.value.length());
}
Param<QVector<int> > values;
Param<double> time;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Run the thread
Worker* worker = new Worker();
QThread* th = new QThread();
worker->moveToThread(th);
QObject::connect(th, &QThread::started, worker, &Worker::run);
Processor CH1_Hard_Soft;
// Will be called when the CH1_Hard_Soft will send its result
QObject::connect(&CH1_Hard_Soft, &Processor::done, [=](double result) { qDebug() << "RESULT" << result; });
// Set the param vector
QObject::connect(worker, &Worker::getVector, [&](QVector<int> const& vec) { CH1_Hard_Soft(vec); });
// Call CH1_Hard_Soft with the first param
double time = 12.6;
CH1_Hard_Soft(time);
th->start();
return app.exec();
I am trying to implement a simple thread starter class. Below you find a Simple base class implementation and 2 derived variations that are supposed to work as starters. The first one throws segfaults at static void* Threaded::run (void* self) sporadically. I suppose this might a pointer issue but I am not able to figure out why?
Does this in Threaded::start point to a wrong address or is there any other issue with my first derivation?
This is how it's used:
Thread thread (ptr_to_some_obj);
thread.start (&this_obj::callback);
thread.detach ();
Simple base class
class Threaded
{
public:
Threaded () {/* empty */}
virtual ~Threaded () {/* empty */}
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool start ()
{
return (pthread_create (&_thread, NULL, run, this) == 0);
}
/** Implement this method in your subclass with the code which allows to gently stop execution. */
virtual void stop () = 0;
/** Will not return until the internal thread has exited. */
void wait ()
{
(void) pthread_join (_thread, NULL);
}
bool detach ()
{
return (pthread_detach (_thread) == 0);
}
protected:
/** Implement this method in your subclass with the code you want your thread to run. */
virtual void run () = 0;
static void* run (void* self)
{
((Threaded*) self) -> run ();
return NULL;
}
pthread_t _thread;
};
Derived class 1 (throws segfault at ((Threaded*) self) -> run (); above)
typedef void (*staticcall)(void*);
class Thread : public Threaded
{
public:
Thread (void* passthru)
:_call (NULL)
{
_passthru = passthru;
}
~Thread () { /* empty */ }
bool start (staticcall call)
{
_call = call;
assert (_call);
return start ();
}
void stop ()
{
// nothing
}
protected:
void run ()
{
(_call) (_passthru);
}
bool start ()
{
return Threaded::start ();
}
private:
Thread () { };
void* _passthru;
staticcall _call;
};
Derived class 2 (works, but i'd rather have Derived class 1 implementation)
typedef void (*staticcall)(void*);
class Thread2 : public Threaded
{
public:
Thread2 (void* passthru)
{
_passthru = passthru;
}
~Thread2 () { /* empty */ }
bool start (staticcall call)
{
_call = call;
assert (_call);
return start ();
}
void stop ()
{
// nothing
}
protected:
void run () { }
static void* run2 (void*)
{
(_call) (_passthru);
return NULL;
}
bool start ()
{
return (pthread_create (&_thread, NULL, run2, NULL) == 0);
}
private:
Thread2 () { };
static void* _passthru;
static staticcall _call;
};
void* Thread2::_passthru;
staticcall Thread2::_call;
As pointed out by molbdnilo:
pthread_create only queues the new thread. There are no guarantees regarding when the thread function will be called, and thread must be alive at that time.
Since I do not want to keep a list of spawned threads around I solved this with the use of pthread_cond_wait and pthread_cond_signal. The spawner will wait for a signal that is emitted by the method that runs in the thread. This way the thread creator won't destroy the thread object before the to-be-threaded method is called.
class ThreadSpawner
{
public:
ThreadSpawner ()
{
pthread_mutex_init (&MtxThreadStarter, 0);
pthread_cond_init (&CondThreadStarter, 0);
}
~ThreadSpawner ()
{
pthread_cond_destroy (&CondThreadStarter);
pthread_mutex_destroy (&MtxThreadStarter);
}
void spawn ()
{
Thread thread (pass_object);
pthread_mutex_lock (&MtxThreadStarter);
if (thread.start (&ThreadSpawner::callback))
{
// wait here for signal
pthread_cond_wait (&CondThreadStarter, &MtxThreadStarter);
thread.detach ();
}
pthread_mutex_unlock (&MtxThreadStarter);
}
static void callback (void* passthru)
{
// send signal to thread spawner
pthread_mutex_lock (&MtxThreadStarter);
pthread_cond_signal (&CondThreadStarter);
pthread_mutex_unlock (&MtxThreadStarter);
// do threaded work
}
private:
static pthread_mutex_t MtxThreadStarter;
static pthread_cond_t CondThreadStarter;
}
pthread_mutex_t ThreadSpawner::MtxThreadStarter = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ThreadSpawner::CondThreadStarter = PTHREAD_COND_INITIALIZER;
Edit: a solution to let a thread execute as a method invokation
Well the solution I thought about in the recent discussion would work if the thread entry point was a simple function.
However, I suppose the idea is more to take advantage of an actual object, so that the thread body is actually an invokation of the body() method.
This is more tricky, since there must be a live instance of the derived class for the whole thread duration, and yet the original instance is likely to get out of scope after a start / detach sequence.
One possible (though somewhat costly) solution is to have the thread body stub create a local copy of the original instance on the stack. So the thread launcher will construct a thread object, and the thread itself will copy it.
With this system, you only need to make sure the original instance will be kept live in the interval between pthread_create and thread activation by the scheduler.
This requires a semaphore (which will be done by hand with a mutex/cond. var. pair for the 1.000.000th time, since bloody C++11 does not have one in store).
To hide this messy code inside the base class, you need to downcast the base pointer into the appropriate subclass type.
I resorted to templating the base class, though there might be smarter solutions out there. I just could not think of any.
To test the solution, I use a counter system that detects whether the original Thread instance has been deleted before the thread stub could make a local copy.
The SYNC compilation flag activates the semaphore. The expected program output is 0->0. If other numbers appear, it means some threads ran on messed-up instances.
I tested it on Ubuntu in a VM, and it seemed to work well enough.
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <thread> // sleep_for
#include <chrono> // milliseconds
#include <pthread.h>
#define SYNC // undefine this to see what happens without synchronization
typedef void *(*tEntryPoint) (void *);
#include <mutex>
#include <condition_variable>
class semaphore {
private:
std::mutex m;
std::condition_variable v;
int c;
public:
semaphore (int count = 0):c(count){}
void V()
{
#ifdef SYNC
std::unique_lock<std::mutex> l(m);
c++;
v.notify_one();
#endif
}
void P()
{
#ifdef SYNC
std::unique_lock<std::mutex> l(m);
while (c == 0) v.wait(l);
c--;
#endif
}
};
template<typename Derived>
class Threaded
{
public:
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool start(void)
{
destructor_guard = new semaphore();
bool res = (pthread_create(&_thread, NULL, (tEntryPoint)entry_point, this) == 0);
if (res) destructor_guard->P(); // wait fot thread to start execution
delete destructor_guard;
return res;
}
/** This optional method will be executed after the thread main body */
virtual void stop() {}
/** Will not return until the internal thread has exited. */
void wait()
{
(void)pthread_join(_thread, NULL);
}
/** Will let the underlying task run independently */
bool detach()
{
return (pthread_detach(_thread) == 0);
}
private:
static void * entry_point(Derived * self)
{
Derived local_self = *self;
local_self.destructor_guard->V(); // original can be deleted
local_self.body();
local_self.stop();
return NULL;
}
pthread_t _thread;
semaphore* destructor_guard;
};
#define NUM_THREADS 9
#define REPEAT 3000
static int signature[NUM_THREADS + 1] = { 0, };
class Thread : public Threaded<Thread>
{
unsigned id;
public:
Thread(unsigned id) : id(id) {}
~Thread() { id = 0; }
void body(void)
{
signature[id%(NUM_THREADS+1)]++;
}
void stop(void)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
signature[id%(NUM_THREADS+1)]++;
}
};
void launch_a_thread(int id)
{
Thread thread (id);
if (thread.start())
{
// thread.wait();
thread.detach();
}
}
int main(void)
{
for (unsigned i = 0; i != REPEAT*NUM_THREADS; i++) launch_a_thread(1+i%NUM_THREADS);
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // leave enough time for free running threads to terminate
for (int i = 0 ; i <= NUM_THREADS ; i++) if (signature[i] != 2*REPEAT) printf ("%d -> %d\n", i, signature[i]);
return 0;
}
I have the following code that implements a Signal/Slot + Concurrency in Qt and was wondering if I can convert this to Boost/Threads and Boost/signal2
void MyClass::Func1()
{
emit ImplementingFunc1();
//Do the stuff here
Func1Implementation()
QFuture<void> future = QtConcurrent::run(this, &MyClass::WaitForFunc1Finish());
}
void MyClass::WaitForFunc1Finish()
{
int result = GetResponse();
emit Func1HasFinished();
}
How can I implement the emit functions (in the above, these are slots in MyClass) and the pipeline using Boost?
Thanks in advance for the help
You could implement your requirements using boost. However, the signals are different because boost does not give you an event loop to dispatch signals to slots.
It means that slot connected to a boost signal called a in thread will be executed in that thread !.
Roughly:
MyClass.h
typedef boost::signals2::signal<void ()> FinishedSig;
typedef boost::shared_ptr<FinishedSig> FinishedSigPtr;
typedef boost::lock_guard<boost::mutex> LockGuard;
class MyClass
{
public:
// Signal
FinishedSig& finished() { return *m_sig; }
void Func1();
void WaitForFunc1Finish();
void WaitForFunc1FinishSlot();
private:
FinishedSigPtr m_sig;
boost::mutex m_mutex;
boost::thread m_thread;
}
MyClass.cpp
// Signal connection
this->finished().connect(boost::bind(&MyClass::Func1HasFinishedSlot, this));
void MyClass::Func1()
{
//Do the stuff here
Func1Implementation()
m_thread = boost::thread(&MyClass::WaitForFunc1Finish, this);
}
void MyClass::WaitForFunc1Finish()
{
LockGuard l(m_mutex);
// Variables are guarded against concurrent access here
int result = GetResponse();
(*m_sig)(); // emit finished sig
}
void MyClass::Func1HasFinishedSlot()
{
// This will be executed in the calling thread
LockGuard l(m_mutex);
// Variables are guarded against concurrent access here
// do stuff
}
I've started a form in new thread, because of some GUI lagging (form become non responsive) problems. This thread starts when a function (some_function()) is called. Such as...
/*========some_function=========*/
void some_function()
{
System::Threading::Thread^ t1;
System::Threading::ThreadStart^ ts = gcnew System::Threading::ThreadStart(&ThreadProc);
t1 = gcnew System::Threading::Thread(ts);
t1->Start();
while(condition)
{
Form1^ f1=gcnew Form1();
//some coding
//to change the values of a different form (Form1)
}
}
/*======ThreadProc=========*/
void ThreadProc()
{
Form1^ f1=gcnew Form1();
f1->Show(); //OR Application::Run(Form1());
}
Now the problem is about changing values of the form (Form1), such as label text, progress bar etc., within the "while" loop. Is tehre any way to change values of form, which is open in different thread ?
Check the Control::Invoke to throw a method into a safe thread to change a control. To show the form of your example:
public delegate void SwapControlVisibleDelegate(Control^ target);
public ref class Form1 : public System::Windows::Forms::Form
{
/*Ctor and InitializeComponents for Form1*/
/*...*/
protected :
virtual void OnShown(EventArgs^ e) override
{
__super::OnShown(e);
some_function();
}
void some_function()
{
System::Threading::Thread^ t1;
System::Threading::ThreadStart^ ts = gcnew ystem::Threading::ThreadStart(this, &Form1::ThreadProc);
t1 = gcnew System::Threading::Thread(ts);
t1->Start();
}
void ThreadProc()
{
Threading::Thread::Sleep(2000);
for each(Control^ c in this->Controls)
{
SwapVisible(c);
}
}
void SwapVisible(Control^ c)
{
if(c->InvokeRequired) // If this is not a safe thread...
{
c->Invoke(gcnew SwapControlVisibleDelegate(this, &Form1::SwapVisible), (Object^)c);
}else{
c->Visible ^= true;
}
}
}
This is how to call a method control into the a safe thread for doing changes.
Right now I have read your comment for the question. Take a look on BackgroundWorker component, it is perfect to run asynchronous task with cancellation support and also it implements events to receive notifications about progress and end of the tasks.