In the original example we have a class, Writer, that extends QThread and that in its run() method writes something. But what if we would like that all the Writer object would run a function that could be set at runtime? A possible solution to this requirement is based on function pointers.
In my main file I have written this function:
static QMutex mio; // 1.
void doSomething(const char* msg, int i)
QMutexLocker qml(&mio); // 2.
std::cout << msg << ", thread id " << QThread::currentThreadId() // 3.
<< " value " << i << std::endl;
1. Since we are about to work in a multithreaded environment, and since we'll have many threads competing on the output console, we'll use a mutex to avoid mixups.
2. Using a lock on the mutex we ensure it would be correctly released at the end of the block.
3. We print the thread id and the data passed by the caller.
We want all the object instantiating Writer calling this doSomething() function (and possibly other functions having the same prototype). To do that, I have refactored the Writer class definition in this way:
typedef void(*MY_FUN)(const char*, int); // 1.
class Writer : public QThread
explicit Writer(int value);
static void setCallback(MY_FUN fun); // 2.
static MY_FUN callback_; // 3.
#endif // WRITER_H
1. MY_FUN has been typedeffed as pointer to a function returning void and having two input parameters, a pointer to const char, and an integer.
2. using this static method we could set the callback function available to all Writer objects.
3. the callback_ function pointer is static: all the Writer object refer to the same one.
The static data members have to be defined in the source code, so in writer.cpp I added the callback_ definition:
MY_FUN Writer::callback_ = NULL;Initially there is no callback function pointer defined.
And here is the Writer functions:
void Writer::setCallback(MY_FUN fun)
callback_ = fun;
if(callback_) // 1.
for(int i = 0; i < 20; ++i)
callback_("Running", i); // 2.
1. As always when working with pointers, it is a good idea to check them before trying to use them.
2. Being called from run(), we ensure that our callback function is called in the new thread.
Not a big change in the main function:
int main(int argc, char *argv)
QCoreApplication a(argc, argv);
// terminates in a couple of seconds
QTimer::singleShot(12000, &a, SLOT(quit()));
What we have done, basically, has been externalizing the job done by each sub-thread, so that it could be easily changed even at runtime.