delete Q_GLOBAL_STATIC in correct thread - multithreading

I have an application consisting of an executable and several DLLs.
The exe links a dll statically. This dll creates a worker thread which instantiates a Q_GLOBAL_STATIC object (first access). So this object (derived from QObject) lives in this worker thread.
At program exit this object needs to be destroyed in the worker thread. But it is actually destroyed when the static dll gets unloaded, which is happening in the main thread.
How do I delete this global static object in the correct thread?
I tried manually deleting it when my worker thread finishes. But this results in a crash after my destructor returns.

You need to explicit call destructor on that object like this obj.~Test(); then after check if object is destroyed obj.isDestroyed() if it is not working.
Use QLibrary to load and unload dll ( https://doc.qt.io/archives/qt-4.8/qlibrary.html). Where in Q_GLOBAL_STATIC documentation(https://doc.qt.io/qt-5/qglobalstatic.html#destruction) it is mention that destructor will be called on unload of library or atexit() funciton of application.

I'd like to share my solution. To make it work, I introduced a simple private class which I use as a QGlobalStatic. This global object of this class holds the real singleton object and allows safe deletion of it in the correct thread.
The header file:
class MySingletonPrivate;
class MySingleton : public QObject
{
Q_OBJECT
public:
static MySingleton* instance();
static void deleteInstance();
protected:
MySingleton( QObject *parent = nullptr );
~MySingleton();
friend class MySingletonPrivate;
};
The cpp file:
class MySingletonPrivate
{
public:
MySingletonPrivate()
: inst( new MySingleton() )
{
QObject::connect( QThread::currentThread(), &QThread::finished, inst, &MySingleton::deleteLater );
}
~MySingletonPrivate()
{
Q_ASSERT( inst.isNull() );
}
MySingleton* instance() const
{
return inst;
}
private:
QPointer< MySingleton > inst;
};
Q_GLOBAL_STATIC( MySingletonPrivate, s_instance );
MySingleton* MySingleton::instance()
{
return s_instance->instance();
}
void MySingleton::deleteInstance()
{
delete s_instance->instance();
}
Using the signal QThread::finished the global instance is deleted at the end of the worker thread.
I left out the include instructions and the constructor and destructor implemention to make the answer shorter.
Of course, the first call to MySingleton::instance() must happen in the worker thread.

Related

How to properly stop thread in class when the class is exposed to QML

I have a class that is exposed to QML:
qmlRegisterType("SerialThread", 1, 0, "SerialThread");
This class inherits QThread and the QThread.start() is called from QML.
When the user closes the application, how do I properly exit the thread before the program terminates?
In the destructor, you should call quit() followed by wait(). Since, hopefully, you've made QML own the thread object, it will destruct it - feel free to verify that the destructor is, in fact, executed.
If you don't spin an event loop in the thread, then you must reimplement quit() to set your own stop flag. Since you hide the underlying non-virtual quit(), your "thread" is not really a QThread anymore, and you must inherit from QThread privately - it's a semantic error to do otherwise (and leads to bad bugs).
How such bugs happen? Since you can pass your "not quite" a thread somewhere a QThread is expected, those users of it are free to assume it's a real thread, not a "not quite one", and call QThread::quit() method, which is a no-op without an event loop. Thus bugs.
To maintain LSP, if you need to override non-virtual public methods, you must privately inherit from the parent class, since it's not usable in places where its parent would be usable.
class MyThread : private QThread {
Q_OBJECT
Q_DISABLE_COPY(MyThread)
volatile bool m_stop;
void run() { ... }
public:
MyThread(QObject * parent = nullptr) : QThread(parent) { ... }
void quit() { m_stop = true; }
// It's important to fully qualify the Priority type, otherwise moc will generate
// wrong code.
Q_SLOT void start(QThread::Priority priority = InheritPriority) {
if (isRunning()) return;
m_stop = false;
QThread::start();
}
using QThread::isRunning;
using QThread::isFinished;
bool isInterruptionRequested() const { return m_stop; }
~MyThread() {
quit();
wait();
}
// Publicly we're only a QObject, not a thread
operator QObject&() { return *this; }
operator const QObject&() const { return *this; }
void run() {
while (!m_stop) { ... }
}
};
You can call thread.stop() and check thread.isRunning() before returning exit value in the main.

DoCallBack CrossAppDomainDelegate behavior for non-static delegates

Please consider the following piece of code:
// Create a new application domain
AppDomain ad = AppDomain.CreateDomain("New domain");
Worker work = new Worker();
// if Worker class is marked as 'MarshalByRefObject', this will run in current
// appdomain.
// if Worker class is NOT marked as 'MarshalByRefObject' and is marked as
// 'Serializable', this will run in a new appdomain.
ad.DoCallBack(work.PrintDomain);
// or ad.DoCallBack(new CrossAppDomainDelegate(work.PrintDomain));
// But for static methods:
// If ppp method is static, no marking is required and it will run in
// a new AppDomain.
ad.DoCallBack(Worker.ppp);
How do we explain this behavior of DoCallBack?
Why is the non-static method PrintDomain executed in the current domain when the Worker class is marked MarshalByRefObject?
Why is the non-static method PrintDomain executed in a new AppDomain when the Worker class is marked Serializable?
Why doesn't the static method need any markings?
Why is the non-static method PrintDomain executed in the current domain when the Worker class is marked MarshalByRefObject?
Because that's what MBRO does, it creates a proxy for the object that you created in your primary appdomain. Which marshals the call from the secondary appdomain to the appdomain that owns the object, the primary appdomain.
Why is the non-static method PrintDomain executed in a new AppDomain when the Worker class is marked Serializable?
Because that scenario does not use a proxy. The object itself is marshaled from the primary to the secondary appdomain. Possible because you marked it [Serializable]. The call therefore executes in the secondary appdomain.
Why doesn't the static method need any markings?
It is unclear what you mean by "markings", but it isn't any different for a static method. Some code to play with, remove the comment on the base class to compare the two scenarios:
using System;
class Program {
static void Main(string[] args) {
var dom = AppDomain.CreateDomain("Test");
var obj = new WorkerMbro();
dom.DoCallBack(obj.PrintDomain);
dom.DoCallBack(obj.PrintDomainStatic);
Console.ReadLine();
}
}
[Serializable]
class WorkerMbro /* : MarshalByRefObject */ {
public void PrintDomain() {
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
}
public void PrintDomainStatic() {
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
}
}
Output as posted:
Test
Test
Output with the comments removed so the proxy is used:
ConsoleApplication1.vshost.exe
ConsoleApplication1.vshost.exe

C# set clipboard data from class

i have a public class , in that class i have a void which sets Clipboard.Text and i have a thread from which i call that func, everytime i call it i get
Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.
I have tried the following :
Thread t = new Thread(Worker);
t.SetApartmentState(ApartmentState.STA);
t.Start();
But i still recieve error, i even tried [STAThread]
My function looks like this
public void Set(string s)
{
Clipboard.SetText(s);
}
I believe it is telling you put put the STAThread attribute on your main function, like so:
[STAThread]
static void Main()
{
// Your code
}
You said you tried STAThread, but was it on the main function or the function you're calling?

QT: run independent thread from other thread

Let me just give you an example.
class B : public QThread {
public:
void run() {
}
};
class A : public QThread {
public:
void run() {
b1.start(); b2.start();
}
protected:
B b1, b2;
};
I want A::b1 and A::b2 to run as completely independent threads, not sharing resources of parent thread (A). Is there any way to specify main thread as parent thread of b1 and b2?
I've also looked at QThreadPool and QRunnable, and i don't understand, how is it possible to manage all runnables (for example, stop one of them, and then run it again) of threadpool.
Subclassing QThread is the wrong way of creating threads in Qt. QObject provides the function moveToThread which simply allows you to change the thread affinity of an object and its children.
Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.
To move an object to the main thread, use QApplication::instance() to
retrieve a pointer to the current application, and then use
QApplication::thread() to retrieve the thread in which the application
lives.
So what you should do is to is to inherit from QObject instead of QThread and change your run function to move the B objects to other threads.
Sample Code (untested)
class B : public QObject {
Q_OBJECT
public:
void run() {
}
};
class A : public QObject {
Q_OBJECT
public:
void run() {
b1Thread = new QThread;
b2Thread = new QThread;
b1.moveToThread(b1Thread);
b2.moveToThread(b2Thread);
b1.run();
b2.run();
}
protected:
B b1, b2;
private:
QThread* b1Thread, b2Thread; // Delete them in the destructor.
};
You could construct the threads in main.cpp and pass them to the B class as arguments.
Notice the following concerning moveToThread
this function can only "push" an object from the current thread to
another thread, it cannot "pull" an object from any arbitrary thread
to the current thread.

QFuture that can be cancelled and report progress

The QFuture class has methods such as cancel(), progressValue(), etc. These can apparently be monitored via a QFutureWatcher. However, the documentation for QtConcurrent::run() reads:
Note that the QFuture returned by
QtConcurrent::run() does not support
canceling, pausing, or progress
reporting. The QFuture returned can
only be used to query for the
running/finished status and the return
value of the function.
I have looked in vain for what method actually can create a QFuture that can be cancelled and report progress for a single long-running operation. (It looks like maybe QtConcurrent::map() and similar functions can, but I just have a single, long-running method.)
(For those familiar with .Net, something like the BackgroundWorker class.)
What options are available?
Though it's been a while since this question was posted and answered I decided to add my way of solving this problem because it is rather different from what was discussed here and I think may be useful to someone else. First, motivation of my approach is that I usually don't like to invent own APIs when framework already has some mature analogs. So the problem is: we have a nice API for controlling background computations represented by the QFuture<>, but we have no object that supports some of the operations. Well, let's do it. Looking on what's going on inside QtConcurrent::run makes things much clearer: a functor is made, wrapped into QRunnable and run in the global ThreadPool.
So I created generic interface for my "controllable tasks":
class TaskControl
{
public:
TaskControl(QFutureInterfaceBase *f) : fu(f) { }
bool shouldRun() const { return !fu->isCanceled(); }
private:
QFutureInterfaceBase *fu;
};
template <class T>
class ControllableTask
{
public:
virtual ~ControllableTask() {}
virtual T run(TaskControl& control) = 0;
};
Then, following what is made in qtconcurrentrunbase.h I made q-runnable for running this kind of tasks (this code is mostly from qtconcurrentrunbase.h, but slightly modified):
template <typename T>
class RunControllableTask : public QFutureInterface<T> , public QRunnable
{
public:
RunControllableTask(ControllableTask<T>* tsk) : task(tsk) { }
virtial ~RunControllableTask() { delete task; }
QFuture<T> start()
{
this->setRunnable(this);
this->reportStarted();
QFuture<T> future = this->future();
QThreadPool::globalInstance()->start(this, /*m_priority*/ 0);
return future;
}
void run()
{
if (this->isCanceled()) {
this->reportFinished();
return;
}
TaskControl control(this);
result = this->task->run(control);
if (!this->isCanceled()) {
this->reportResult(result);
}
this->reportFinished();
}
T result;
ControllableTask<T> *task;
};
And finally the missing runner class that will return us controllable QFututre<>s:
class TaskExecutor {
public:
template <class T>
static QFuture<T> run(ControllableTask<T>* task) {
return (new RunControllableTask<T>(task))->start();
}
};
The user should sublass ControllableTask, implement background routine which checks sometimes method shouldRun() of TaskControl instance passed to run(TaskControl&) and then use it like:
QFututre<int> futureValue = TaskExecutor::run(new SomeControllableTask(inputForThatTask));
Then she may cancel it by calling futureValue.cancel(), bearing in mind that cancellation is graceful and not immediate.
I tackled this precise problem a while ago, and made something called "Thinker-Qt"...it provides something called a QPresent and a QPresentWatcher:
http://hostilefork.com/thinker-qt/
It's still fairly alpha and I've been meaning to go back and tinker with it (and will need to do so soon). There's a slide deck and such on my site. I also documented how one would change Mandelbrot to use it.
It's open source and LGPL if you'd like to take a look and/or contribute. :)
Yan's statement is inaccurate. Using moveToThread is one way of achieving the proper behavior, but it not the only method.
The alternative is to override the run method and create your objects that are to be owned by the thread there. Next you call exec(). The QThread can have signals, but make sure the connections are all Queued. Also all calls into the Thread object should be through slots that are also connected over a Queued connection. Alternatively function calls (which will run in the callers thread of execution) can trigger signals to objects that are owned by the thread (created in the run method), again the connections need to be Queued.
One thing to note here, is that the constructor and destructor are running in the main thread of execution. Construction and cleanup need to be performed in run. Here is an example of what your run method should look like:
void MythreadDerrivedClass::run()
{
constructObjectsOnThread();
exec();
destructObjectsOnThread();
m_waitForStopped.wakeAll();
}
Here the constructObjectsOnThread will contain the code one would feel belongs in the constructor. The objects will be deallocated in destructObjectsOnThread. The actual class constructor will call the exit() method, causing the exec() to exit. Typically you will use a wait condition to sit in the destructor till the run has returned.
MythreadDerivedClass::~MythreadDerivedClass()
{
QMutexLocker locker(&m_stopMutex);
exit();
m_waitForStopped.wait(locker.mutex(), 1000);
}
So again, the constructor and destructor are running in the parent thread. The objects owned by the thread must be created in the run() method and destroyed before exiting run. The class destructor should only tell the thread to exit and use a QWaitCondition to wait for the thread to actually finish execution. Note when done this way the QThread derived class does have the Q_OBJECT macro in the header, and does contain signals and slots.
Another option, if you are open to leveraging a KDE library, is KDE's Thread Weaver. It's a more complete task based multitasking implementation similar QtConcurrentRun in that it leverages a thread pool. It should be familiar for anyone from a Qt background.
That said, if you are open to a c++11 method of doing the same thing, I would look at std::async. For one thing, you will no longer have any dependance on Qt, but the api also makes more clear what is going on. With MythreadDerivedClass class inheriting from QThread, the reader gets the impression that MythreadDerivedClass is a thread (since it has an inheritance relationship), and that all its functions run on a thread. However, only the run() method actually runs on a thread. std::async is easier to use correctly, and has fewer gotcha's. All our code is eventually maintained by someone else, and these sorta things matter in the long run.
C++11 /w QT Example:
class MyThreadManager {
Q_OBJECT
public:
void sndProgress(int percent)
void startThread();
void stopThread();
void cancel() { m_cancelled = true; }
private:
void workToDo();
std::atomic<bool> m_cancelled;
future<void> m_threadFuture;
};
MyThreadedManger::startThread() {
m_cancelled = false;
std::async(std::launch::async, std::bind(&MyThreadedManger::workToDo, this));
}
MyThreadedManger::stopThread() {
m_cancelled = true;
m_threadfuture.wait_for(std::chrono::seconds(3))); // Wait for 3s
}
MyThreadedManger::workToDo() {
while(!m_cancelled) {
... // doWork
QMetaInvoke::invokeMethod(this, SIGNAL(sndProgress(int)),
Qt::QueuedConnection, percentDone); // send progress
}
}
Basically, what I've got here isn't that different from how your code would look like with QThread, however, it is more clear that only workToDo() is running on the thread and that MyThreadManager is only managing the thread and not the thread itself. I'm also using MetaInvoke to send a queued signal for sending our progress updates with takes care of the progress reporting requirement. Using MetaInvoke is more explicit and always does the right thing (doesn't matter how you connect signals from your thread managers to other class's slots). You can see that the loop in my thread checks an atomic variable to see when the process is cancelled, so that handles the cancellation requirement.
Improve #Hatter answer to support Functor.
#include <QFutureInterfaceBase>
#include <QtConcurrent>
class CancellationToken
{
public:
CancellationToken(QFutureInterfaceBase* f = NULL) : m_f(f){ }
bool isCancellationRequested() const { return m_f != NULL && m_f->isCanceled(); }
private:
QFutureInterfaceBase* m_f;
};
/*== functor task ==*/
template <typename T, typename Functor>
class RunCancelableFunctorTask : public QtConcurrent::RunFunctionTask<T>
{
public:
RunCancelableFunctorTask(Functor func) : m_func(func) { }
void runFunctor() override
{
CancellationToken token(this);
this->result = m_func(token);
}
private:
Functor m_func;
};
template <typename Functor>
class RunCancelableFunctorTask<void, Functor> : public QtConcurrent::RunFunctionTask<void>
{
public:
RunCancelableFunctorTask(Functor func) : m_func(func) { }
void runFunctor() override
{
CancellationToken token(this);
m_func(token);
}
private:
Functor m_func;
};
template <class T>
class HasResultType
{
typedef char Yes;
typedef void *No;
template<typename U> static Yes test(int, const typename U::result_type * = 0);
template<typename U> static No test(double);
public:
enum { Value = (sizeof(test<T>(0)) == sizeof(Yes)) };
};
class CancelableTaskExecutor
{
public:
//function<T or void (const CancellationToken& token)>
template <typename Functor>
static auto run(Functor functor)
-> typename std::enable_if<!HasResultType<Functor>::Value,
QFuture<decltype(functor(std::declval<const CancellationToken&>()))>>::type
{
typedef decltype(functor(std::declval<const CancellationToken&>())) result_type;
return (new RunCancelableFunctorTask<result_type, Functor>(functor))->start();
}
};
User example:
#include <QDateTime>
#include <QDebug>
#include <QTimer>
#include <QFuture>
void testDemoTask()
{
QFuture<void> future = CancelableTaskExecutor::run([](const CancellationToken& token){
//long time task..
while(!token.isCancellationRequested())
{
qDebug() << QDateTime::currentDateTime();
QThread::msleep(100);
}
qDebug() << "cancel demo task!";
});
QTimer::singleShot(500, [=]() mutable { future.cancel(); });
}
For a long running single task, QThread is probably your best bet. It doesn't have build-in progress reporting or canceling features so you will have to roll your own. But for simple progress update it's not that hard. To cancel the task, check for a flag that can be set from calling thread in your task's loop.
One thing to note is if you override QThread::run() and put your task there, you can't emit signal from there since the QThread object is not created within the thread it runs in and you can't pull the QObject from the running thread. There is a good writeup on this issue.

Resources