poke thread
authorKonrad Rosenbaum <konrad@silmor.de>
Mon, 25 Feb 2013 19:29:24 +0000 (20:29 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Mon, 25 Feb 2013 19:29:24 +0000 (20:29 +0100)
LIESMICH.txt
main/main.cpp
main/main.h
main/thready.cpp
main/thready.h

index b2e262e..7bc4362 100644 (file)
@@ -150,3 +150,32 @@ liegt in einer DLL/so. (Das mache ich zum Beispiel in einem Projekt auf
 Arbeit so.)
 
 Im Beispiel ist die Funktions-DLL in base und die Plugins in dylib*.
+
+Die getthingy Funktion in den Libs implementiert übrigens das "Factory-Pattern".
+Ja, so einfach können Buzzwords aussehen... ;-)
+
+Thread und Proxy
+-----------------
+
+Siehe main/thready.*
+
+Das Thread-Objekt ist so einfach wie möglich: nur eine Startroutine, die
+alle nötigen Parameter übernimmt und ein run(), welches das eigentliche
+Task-Objekt instantiiert.
+
+Die MyThread-Klasse ist dabei eine sog. Fasade oder ein Proxy. Die Arbeit
+wird von MyTask gemacht. Damit lässt sich in diesem Fall auch garantieren
+dass alle wichtigen Slots im richtigen Thread sind.
+
+Eine andere Variante den Thread zu implementieren, wäre den Konstruktor
+public zu machen, noch 0-viele setter für weitere Parameter und dann 
+wird start()/run() aufgerufen...
+
+Wenn mit dem Thread kommuniziert werden muss dann benutzt man Signal-Slot-
+Kaskaden, siehe disruptThread()...
+
+QPointer
+--------
+
+...ist sehr praktisch wenn man ein QObject nicht besitzt oder es sich
+unvermittelt löschen kann. So wie unser Thread.
\ No newline at end of file
index f462e62..3417b22 100644 (file)
@@ -33,6 +33,8 @@ MainWin::MainWin()
         vl->addSpacing(10);
         vl->addWidget(p=new QPushButton("Start Thread"));
         connect(p,SIGNAL(clicked(bool)),this,SLOT(startThread()));
+        vl->addWidget(p=new QPushButton("Poke Thread"));
+        connect(p,SIGNAL(clicked(bool)),this,SLOT(pokeThread()));
 }
 
 
@@ -88,7 +90,15 @@ void MainWin::loadLib2()
 void MainWin::startThread()
 {
         //start a thread and let it update the label automatically
-        MyThread::startMe(mthingylabel,SLOT(setText(QString)));
+        mthread=MyThread::startMe(mthingylabel,SLOT(setText(QString)));
+}
+
+void MainWin::pokeThread()
+{
+        if(mthread.isNull())
+                mthingylabel->setText("Sorry, cannot poke a null thread");
+        else
+                mthread->disruptThread();
 }
 
 
index fc52e19..8bec118 100644 (file)
@@ -3,7 +3,9 @@
 
 #include <QDialog>
 #include "../base/thingy.h"
+#include <QPointer>
 
+class MyThread;
 class QLabel;
 class QLibrary;
 
@@ -23,6 +25,8 @@ class MainWin:public QDialog
                 void unloadLib();
                 ///starts a thread to do stuff in the background
                 void startThread();
+                ///does funny things with the thread
+                void pokeThread();
                 
                 ///call that thingy from one of those libraries
                 void callThingy();
@@ -33,6 +37,7 @@ class MainWin:public QDialog
                 QLibrary*mthinglib;
                 //the thingy from that library
                 Thingy*mthingy;
+                QPointer<MyThread>mthread;
 };
 
 #endif
\ No newline at end of file
index 0683aef..58beffb 100644 (file)
@@ -1,12 +1,13 @@
 #include "thready.h"
 #include <QTimer>
 
-void MyThread::startMe(QObject* c, const char* s)
+MyThread* MyThread::startMe(QObject* c, const char* s)
 {
         //create thread and remember connection to the outside world
         MyThread *m=new MyThread(c,s);
         //start it
         m->start();
+        return m;
 }
 
 MyThread::MyThread(QObject* callee, const char* slot): QThread(callee)
@@ -33,6 +34,8 @@ void MyThread::run()
         //make sure it deletes itself
         // Qt::AutoConnection effectively: Qt::DirectConnection - same object
         connect(this,SIGNAL(finished()),this,SLOT(deleteLater()));
+        //initiate cascade
+        connect(this,SIGNAL(disruptThreadSignal()), &task,SLOT(disruptThread()), Qt::QueuedConnection);
         //now loop for a while
         exec();
 }
@@ -42,3 +45,14 @@ void MyTask::gotime()
         //simply count up and tell everyone
         emit updateString(QString("Hello, I'm a thread and can count to %1").arg(ctr++));
 }
+
+void MyThread::disruptThread()
+{
+        emit disruptThreadSignal();
+}
+
+void MyTask::disruptThread()
+{
+        ctr+=1000;
+        gotime();
+}
index 5b20600..136dc28 100644 (file)
@@ -4,6 +4,7 @@
 ///It does not know much about what is done there.
 class MyThread:public QThread
 {
+        Q_OBJECT
         public:
                 ///not needed, use startMe
                 MyThread()=delete;
@@ -11,7 +12,11 @@ class MyThread:public QThread
                 ///start the thread
                 ///\param callee the object that gets the updated information, also owner of the thread object
                 ///\param slot the slot to call for updates, must be SLOT(foo(QString)) or SLOT(foo())
-                static void startMe(QObject*callee,const char*slot);
+                static MyThread* startMe(QObject*callee,const char*slot);
+        public slots:
+                void disruptThread();
+        signals:
+                void disruptThreadSignal();
         protected:
                 ///internal: creates the thread and remembers who to call
                 MyThread(QObject* callee,const char*slot);
@@ -34,6 +39,8 @@ class MyTask:public QObject
         private slots:
                 ///called to update the thread status
                 void gotime();
+                ///called from cascade
+                void disruptThread();
         signals:
                 ///sent to the outside world when the thread has something to say
                 void updateString(QString);