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