class SomeJob: public QObject { Q_OBJECT public: SomeJob () { /* ... */ } // ~SomeJob () { /* ... */ } // signals: void finished (); // public slots: void to_terminate () { /* ... */ } // }; ... ThreadedObject<SomeJob> thr; // - thr.start (); //
class CreatorBase: public QObject { Q_OBJECT void *_obj; protected: virtual void *Allocation (void) = 0; public slots: void allocate (void) { emit setObject (Allocation ()); } signals: void setObject (void *Obj); }; template <class T> class Creator: public CreatorBase { protected: void *Allocation (void) { return reinterpret_cast <void*> (new T); } };
class ThreadedObjectBase: public QObject { Q_OBJECT protected: QThread *_thread; virtual void SetObjectPointer (void *Ptr) = 0; ThreadedObjectBase (QObject *parent = 0): QObject (parent), _thread (0) {} void starting (CreatorBase *Creator, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true) { bool res; _thread = new QThread; Creator->moveToThread (_thread); res = connect (_thread, SIGNAL (started ()), Creator, SLOT (allocate ())); Q_ASSERT_X (res, "connect", "connection is not established"); res = connect (Creator, SIGNAL (setObject (void*)), this, SLOT (setObject (void*))); Q_ASSERT_X (res, "connect", "connection is not established"); if (ToDeleteLaterThread) { res = connect (_thread, SIGNAL (finished ()), _thread, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } _thread->start (Priority); } public: virtual ~ThreadedObjectBase (void) { } QThread *thread (void) { return _thread; } const QThread *cthread (void) const { return _thread; } signals: void objectIsReady (void); private slots: void setObject (void *Obj) { SetObjectPointer (Obj); emit objectIsReady (); } };
template <class T> class ThreadedObject: public ThreadedObjectBase { protected: T* _obj; Creator<T> _creator; const char *_finished_signal; const char *_terminate_slot; bool _to_delete_later_object; void SetObjectPointer (void *Ptr) { bool res; _obj = reinterpret_cast <T*> (Ptr); if (_finished_signal) { res = connect (_obj, _finished_signal, _thread, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); } if (_terminate_slot) { res = connect (_thread, SIGNAL (finished ()), _obj, _terminate_slot); Q_ASSERT_X (res, "connect", "connection is not established"); } if (_to_delete_later_object && _finished_signal) { res = connect (_obj, _finished_signal, _obj, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } } public: ThreadedObject (QObject *parent = 0): ThreadedObjectBase (parent), _obj (0) { } ~ThreadedObject (void) { } void start (const char *FinishedSignal = 0, const char *TerminateSlot = 0, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true, bool ToDeleteLaterObject = true) { Creator<T> *creator = new Creator<T>; _finished_signal = FinishedSignal; _terminate_slot = TerminateSlot; _to_delete_later_object = ToDeleteLaterObject; starting (_creator, Priority, ToDeleteLaterThread); delete creator; } bool objectIsCreated (void) const { return _obj != 0; } T* ptr (void) { return reinterpret_cast <T*> (_obj); } const T* cptr (void) const { return reinterpret_cast <const T*> (_obj); } // . operator T* (void) { return ptr (); } T* operator -> (void) { return ptr (); } operator const T* (void) const { return cptr (); } const T* operator -> (void) const { return cptr (); } };
ThreadedObject <Operation> _obj; QObject::connect (&_obj, SIGNAL (objectIsReady ()), this, SLOT (connectObject ())); _obj.start (SIGNAL (finished ()), SLOT (terminate ()), QThread::HighPriority);
// ** // ** // ** class CreatorBase: public QObject { Q_OBJECT void *_obj; // protected: virtual void *Allocation (void) = 0; // public slots: void allocate (void) { emit setObject (Allocation ()); } // signals: void setObject (void *Obj); // }; // ** // ** // ** class ThreadedObjectBase: public QObject { Q_OBJECT protected: QThread *_thread; // virtual void SetObjectPointer (void *Ptr) = 0; // ThreadedObjectBase (QObject *parent = 0): QObject (parent), _thread (0) {} // void starting (CreatorBase *Creator, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true) // { bool res; // - _thread = new QThread; // Creator->moveToThread (_thread); // _creator res = connect (_thread, SIGNAL (started ()), Creator, SLOT (allocate ())); Q_ASSERT_X (res, "connect", "connection is not established"); // _thread Creator- res = connect (Creator, SIGNAL (setObject (void*)), this, SLOT (setObject (void*))); Q_ASSERT_X (res, "connect", "connection is not established"); // Creat- if (ToDeleteLaterThread) // thread? { res = connect (_thread, SIGNAL (finished ()), _thread, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } // _thread _thread->start (Priority); // } public: // . virtual ~ThreadedObjectBase (void) { } // QThread *thread (void) { return _thread; } // , // . const QThread *cthread (void) const { return _thread; } // , signals: void objectIsReady (void); // " " private slots: void setObject (void *Obj) { SetObjectPointer (Obj); emit objectIsReady (); } // }; // class ThreadedObjectBase // ** // ** // ** template <class T> class ThreadedObject: public ThreadedObjectBase { private: template <class T> class Creator: public CreatorBase // { protected: void *Allocation (void) { return reinterpret_cast <void*> (new T); } }; protected: T* _obj; // Creator<T> _creator; // const char *_finished_signal; // " " const char *_terminate_slot; // " " bool _to_delete_later_object; // " ? void SetObjectPointer (void *Ptr) // { bool res; // - _obj = reinterpret_cast <T*> (Ptr); // if (_finished_signal) // " "? { res = connect (_obj, _finished_signal, _thread, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); } // if (_terminate_slot) // " "? { res = connect (_thread, SIGNAL (finished ()), _obj, _terminate_slot); Q_ASSERT_X (res, "connect", "connection is not established"); } // " " if (_to_delete_later_object && _finished_signal) // ? { res = connect (_obj, _finished_signal, _obj, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } // } public: // . ThreadedObject (QObject *parent = 0): ThreadedObjectBase (parent), _obj (0) {} // ~ThreadedObject (void) { } // void start (const char *FinishedSignal = 0, const char *TerminateSlot = 0, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true, bool ToDeleteLaterObject = true) // { _finished_signal = FinishedSignal; // " " _terminate_slot = TerminateSlot; // " " _to_delete_later_object = ToDeleteLaterObject; // starting (_creator, Priority, ToDeleteLaterThread); // } // . bool objectIsCreated (void) const { return _obj != 0; } // ? T* ptr (void) { return reinterpret_cast <T*> (_obj); } // const T* cptr (void) const { return reinterpret_cast <const T*> (_obj); } // // . operator T* (void) { return ptr (); } // T* operator -> (void) { return ptr (); } // operator const T* (void) const { return cptr (); } // const T* operator -> (void) const { return cptr (); } // }; // class ThreadedObject
#include <QtGui> #include <QtWidgets> #include <QtCore> #include "ThreadedObject.h" // ** // ** // ** class Operation: public QObject { Q_OBJECT int *Int; // QTimer _tmr; // int _int_timer; // public: Operation (void) { Int = new int (5); } // ~Operation (void) { if (Int) delete Int; } // signals: void addText(const QString &txt); // " " void finished (); // " " public slots: void terminate () // { killTimer (_int_timer); // _tmr.stop (); // delete Int; // Int = 0; // emit finished (); // } void doAction (void) // { bool res; emit addText (QString ("- %1 -"). arg (*Int)); res = QObject::connect (&_tmr, &QTimer::timeout, this, &Operation::timeout); Q_ASSERT_X (res, "connect", "connection is not established"); // _tmr.start (2000); // thread()->sleep (1); // 1 ... timeout (); // ... ... startTimer (2000); // ... } protected: void timerEvent (QTimerEvent *ev) { timeout (); } // private slots: void timeout (void) { if (!Int || !*Int) // ? return; // ... --*Int; // emit addText (QString ("- %1 -"). arg (*Int)); // if (!Int || !*Int) // ? emit finished (); // ... } }; // ** // ** , // ** class App: public QObject { Q_OBJECT ThreadedObject <Operation> _obj; // - QPushButton _btn; // protected: void timerEvent (QTimerEvent *ev) { bool res; // - killTimer (ev->timerId ()); // res = QObject::connect (&_obj, SIGNAL (objectIsReady ()), this, SLOT (connectObject ())); Q_ASSERT_X (res, "connect", "connection is not established"); // _obj.start (SIGNAL (finished ()), SLOT (terminate ()), QThread::HighPriority); // } private slots: void setText (const QString &txt) { _btn.setText (txt); } // void connectObject (void) // { bool res; // - res = QObject::connect (this, &App::finish, _obj, &Operation::terminate); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (this, &App::startAction, _obj, &Operation::doAction); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (_obj, &Operation::finished, this, &App::finish); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (_obj, &Operation::addText, this, &App::setText); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (&_btn, &QPushButton::clicked, _obj, &Operation::terminate); Q_ASSERT_X (res, "connect", "connection is not established"); // _btn.show (); // emit startAction (); // } public slots: void terminate (void) { emit finish (); } // signals: void startAction (void); // " " void finish (void); // " " }; // ** // ** // ** int main (int argc, char **argv) { QApplication app (argc, argv); // App a; // bool res; // a.startTimer (0); // res = QObject::connect (&a, SIGNAL (finish ()), &app, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (&app, SIGNAL (lastWindowClosed ()), &a, SLOT (terminate ())); Q_ASSERT_X (res, "connect", "connection is not established"); // return app.exec(); // } #include "main.moc"
Source: https://habr.com/ru/post/202312/
All Articles