C++11 thread pool - tasks with input parameters - multithreading

I am trying to use a simple thread pool example from the book of Anthony Williams "C++ Concurrency in Action". I have even found the code here (the class thread_pool) in one of the posts:
Synchronizing tasks
but I have a different question. I would like to submit a task (a member function) to the queue with the following signature:
class A;
class B;
bool MyClass::Func(A*, B*);
How would I need to change the thread_pool class, or how do I pack my function in some void F(), which is assumed to be used as a task in this example?
Here is the most relevant part of the class for me (for the details please see the link above):
class thread_pool
{
thread_safe_queue<std::function<void()> work_queue; // bool MyClass::Func(a,b) ??
void worker_thread() {
while(!done) {
std::function<void()> task;
if(work_queue.try_pop(task)) {
task(); // how should my function MyClass::Func(a,b) be called here?
}
else {
std::this_thread::yield();
}
}
}
// -- Submit a task to the thread pool
template <typename FunctionType>
void submit(FunctionType f) {
work_queue.push(std::function<void()>(f)); // how should bool MyClassFunc(A*, B*) be submitted here
}
}
And finally, how can I call the submit Function in my code?
Thank you very much for your help (unfortunatelly I am not very experienced yet in using all the C++11 features, which is probably also why I need help here, but an answer to this question would be something to start with :)).

You have to bind the parameters to a value when you insert a task into the queue. That means that you have to create a wrapper for your function that stores the values for this and the values for the two function parameters. There are many ways to do this, e.g. lambda functions or std::bind.
work_queue.push_back( [obj, a, b]() {obj->Func(a,b)} );
work_queue.push_back( std::bind(&MyClass::Func, obj, a, b) );
Your submit function must take these parameters and create the binding, e.g.
template<typename F, typename... Args>
void submit(F f, Args&&... args) {
work_queue.push_back( std::bind(f, std::forward<Args>(args)...) );
}
It may be convenient to create a special overload for member functions and objects.

I've written something that does something (very) similar to this before. I'll post the code here and you can have a look. GenCmd is the function wrapper. The queue looks like this, and is used/defined in Impl (code omitted). You only need to look at implementation of GenCmd, as this contains the necessary work.
ConcurrentQueue<std::unique_ptr<Cmd>> cqueue_;
I've wrapped std::function<> to be polymorphic in queue. std_utility contains make_index_sequence, that is used to extract values from a tuple (google make_index_sequence to find an implementation somewhere if this is not already part of your std library).
#include <functional>
#include <memory>
#include <iostream>
#include <utility>
#include <boost/noncopyable.hpp>
class CmdExecutor : public boost::noncopyable
{
public:
CmdExecutor(std::ostream& errorOutputStream);
~CmdExecutor();
template <class Receiver, class ... FArgs, class ... CArgs >
void process(Receiver& receiver, void (Receiver::*f)(FArgs...), CArgs&&... args)
{
process(std::unique_ptr<Cmd>(new GenCmd<void(Receiver,FArgs...)>(f, receiver, std::forward<CArgs>(args)...)));
}
private:
class Cmd
{
public:
virtual void execute() = 0;
virtual ~Cmd(){}
};
template <class T> class GenCmd;
template <class Receiver, class ... Args>
class GenCmd<void(Receiver, Args...)> : public Cmd
{
public:
template <class FuncT, class ... CArgs>
GenCmd(FuncT&& f, Receiver& receiver, CArgs&&... args)
: call_(std::move(f)),
receiver_(receiver),
args_(args...)
{
}
//We must convert references to values...
virtual void execute()
{
executeImpl(std::make_index_sequence<sizeof...(Args)>{});
}
private:
template <std::size_t ... Is>
void executeImpl(std::index_sequence<Is...>)
{
// We cast the values in the tuple to the original type (of Args...)
call_(receiver_, static_cast<Args>(std::get<Is>(args_))...);
}
std::function<void(Receiver&, Args...)> call_;
Receiver& receiver_;
// NOTE:
// References converted to values for safety sake, as they are likely
// to not be around when this is executed in other context.
std::tuple<typename std::remove_reference<Args>::type...> args_;
};
void process(std::unique_ptr<Cmd> command);
class Impl;
Impl* pimpl_;
};
It's basically used as follows:
...
CmdExecutor context_;
...
void MyClass::myFunction()
{
ArgX x;
ArgY y;
context_.process(*this, &MyClass::someFunction, x, y);
}
You can see from this that process does the wrapping of member function type and converts it to the underlying type for storage on queue. This allows for multiple argument types. I've opted for using runtime polymorphism to store the function types, hence the GenCmd derivative.
Note: If the invoked function receives an rvalue (Arg&&), the stored type is casted to the original type, therefore causing a move, and rendering the applicable command argument (which would only be invoked once) empty (that's the intent, at least - untested...)

Related

QtConcurrent::run - Passing Pointers Issue

I'm attempting to run a function concurrently using QtConcurrent but I'm running into issues with one of the arguments.
As a precursor, lets say I have the following classes and "interfaces":
class DataMessage : public QObject {
Q_OBJECT
// ... fields and methods
};
class ITimeStampInfo {
public:
virtual QDateTime timestamp() const = 0;
};
Q_DECLARE_INTERFACE(ITimeStampInfo, "My.TimeStampInfo/1.0")
class IDataLengthInfo {
public:
virtual int dataLength() const = 0;
};
Q_DECLARE_INTERFACE(IDataLengthInfo, "My.IDataLengthInfo/1.0")
class DataMessage1 : public DataMessage, public ITimeStampInfo {
Q_OBJECT
Q_INTERFACES(ITimeStampInfo)
// other fields, etc
QDateTime timestamp() const;
};
class DataMessage2 : public DataMessage, public IDataLengthInfo {
Q_OBJECT
Q_INTERFACES(IDataLengthInfo)
// other fields
int dataLength() const;
};
And a class function called processDataMessages:
void MyClass::processDataMessages(DataMessage *msg) {
// Previous to this function being called, concrete `DataMessage`
// instances are created and passed by pointer into this function
// Determine the data in the message
IDataLengthInfo *dl = qobject_cast<IDataLengthInfo*>(msg);
if (dl) {
qDebug() << "Got a message with IDataLengthInfo";
}
ITimeStampInfo *ts = qobject_cast<ITimeStampInfo*>(msg);
if (ts) {
qDebug() << "Got a message with ITimeStampInfo";
}
// etc
}
This processDataMessages is called in a slot. During normal operation, this function works perfectly and the qDebug() statements execute as expected as the pointer is correct - for example, inspecting the pointer type in the debugger results in a DataMessage1 type, for instance
I now want to run this function asynchronously as potentially, there may be a bit of work to do. If I try to execute this function using QtConcurrent::run from within the slot as follows:
void MyClass::dataReceived(DataMessage *msg) {
// this->processDataMessages(msg);
QtConcurrent::run(this, &MyClass::processDataMessages, msg);
}
Now when I break on the first qobject_cast line in the processDataMessages function, I can see that the msg pointer is of type DataMessage and not any of the DataMessage1 or DataMessage2 types.
Something is being lost during the operation of QtConcurrent::run and its probably something dumb I've missed.
Ok, so as it turns out, the following code works:
QFuture<void> f = QtConcurrent::run(this, &MyClass::processDataMessages, msg);
// Wait for the function to finish
f.waitForFinished();
Doesn't really seem any different to the original but something in the return value may be maintaining state??

QtConcurrent::map() with member function = can not compile

My project is to create a small program which demonstrates the work of a search engine: indexing and returning result for arbitrary queries. I've done the work with the indexer part and now I want to improve it with indexing multiple files at once. The MainWindow class is here:
class MainWindow : public QMainWindow
{
Q_OBJECT
.....
private:
Indexer * indexer;
QStringList fileList;
....
void index(QStringList list);
void add(const QString &filename);
}
This is the implementation of add (add need to access fileList to avoid index the same files again, thus it can not be static method):
void MainWindow::add(const QString &filename)
{
if (!fileList.contains(filename))
{
indexer->addDocument(filename.toStdString());
fileList.append(filename);
qDebug() << "Indexed" << filename;
emit updatedList(fileList);
}
}
The implement of index method is to receive a file lists and call add upon each file name:
void MainWindow::index(QStringList list)
{
....
QtConcurrent::map(list, &MainWindow::add);
....
}
The error I receive when compiling these code is:
usr/include/qt4/QtCore/qtconcurrentmapkernel.h: In member function 'bool QtConcurrent::MapKernel<Iterator, MapFunctor>::runIteration(Iterator, int, void*) [with Iterator = QList<QString>::iterator, MapFunctor = QtConcurrent::MemberFunctionWrapper1<void, MainWindow, const QString&>]':
../search-engine/mainwindow.cpp:361:1: instantiated from here
/usr/include/qt4/QtCore/qtconcurrentmapkernel.h:73:9: error: no match for call to '(QtConcurrent::MemberFunctionWrapper1<void, MainWindow, const QString&>) (QString&)'
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:128:7: note: candidate is:
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:138:14: note: T QtConcurrent::MemberFunctionWrapper1<T, C, U>::operator()(C&, U) [with T = void, C = MainWindow, U = const QString&]
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:138:14: note: candidate expects 2 arguments, 1 provided
I'm not really familiar with how QtConcurrent works, and the documentation doesn't provide much details about it. I really hope that someone here can help. Thanks in advance.
To be able to call a pointer-to-member, you need, in addition to that functions formal arguments, an instance of that class (the this pointer that you get inside member functions).
There are two ways to handle this: create a simple functor to wrap the call, or use a lambda.
The functor would look like this:
struct AddWrapper {
MainWindow *instance;
AddWrapper(MainWindow *w): instance(w) {}
void operator()(QString const& data) {
instance->add(data);
}
};
And you'd use it like:
AddWrapper wrap(this);
QtConcurrent::map(list, wrap);
(Careful with the lifetime of that wrapper though. You could make that more generic - you could also store a pointer-to-member in the wrapper for instance, and/or make it a template if you want to reuse that structure for other types.)
If you have a C++11 compiler with lambdas, you can avoid all that boilerpalte:
QtConcurrent::map(list, [this] (QString const& data) { add(data); });
Note: I'm not sure how QtConcurrent::MemberFunctionWrapper1 got involved in your example, I'm not seeing it here. So there might be a generic wrapper already in Qt for this situation, but I'm not aware of it.

How to return a vector of objects to managed code efficiently?

I have a ref class that contains a pointer to an unmanaged class. the class has some basic types and also a vector of objects of another class. I would like to know the best way to get and set the vector from managed code. Will a memcpy between unmangedb objects be efficient or setting each member variable of unmanagedb?
for ex (assume the class is complete. I am writing what is relevant to the question)
Assume we already have a managed wrapped for struct UnmanagedB called B.
struct UnmanagedA
{
int a;
vector<UnmanagedB> list;
};
public ref class A : public System::IDisposable
{
public:
// properties
property System::UInt32 a
{
System::UInt32 get();
void set(System::UInt32 value);
}
property array<B^>^ list
{
System::array<B^>^ get(); // what is the best way to set and get the vector
void set(array<B^>^ value);
}
private:
UnmanagedA* obj1;
};
This obviously won't be cleanly possible, since UnmanagedA contains a vector of UnmanagedB values, while A exposes an property of type array<B^>. If this is intended and not a typo, you will need to marshall the content of B^ into instances of UnmanagedB. Otherwise, let UnmanagedA hold a std::vector< B* > and take care of proper lifetime management.

how to create a thread using a non static method in vc++ mfc

I am creating a thread using this call:
m_pThread=AfxBeginThread(read_data,(LPVOID)hSerial);
read_data is a static method in my class.
But I want to call a non static method and make a thread.
As I want to share a variable between this thread and one of my class method.
I tried taking a static variable but it gave some errors.
You cannot create a thread using a non-static member of a function as the thread procedure: the reason is all non-static methods of a class have an implicit first argument, this is pointer this.
This
class foo
{
void dosomething();
};
is actually
class foo
{
void dosomething(foo* this);
};
Because of that, the function signature does not match the one you need for the thread procedure. You can use a static method as thread procedure and pass the this pointer to it. Here is an example:
class foo
{
CWindThread* m_pThread;
HANDLE hSerial;
static UINT MyThreadProc(LPVOID pData);
void Start();
};
void foo::Start()
{
m_pThread=AfxBeginThread(MyThreadProc,(LPVOID)this);
}
UINT foo::MyThreadProc(LPVOID pData)
{
foo* self = (foo*)pData;
// now you can use self as it was this
ReadFile(self->hSerial, ...);
return 0;
}
I won't repeat what Marius said, but will add that I use the following:
class foo
{
CWindThread* m_pThread;
HANDLE hSerial;
static UINT _threadProc(LPVOID pData);
UINT MemberThreadProc();
void Start();
};
void foo::Start()
{
m_pThread=AfxBeginThread(_threadProc,(LPVOID)this);
}
UINT foo::MyThreadProc(LPVOID pData)
{
foo* self = (foo*)pData;
// call class instance member
return self->MemberThreadProc();
}
UINT foo::MemberThreadProc()
{
// do work
ReadFile(hSerial, ...);
return 0;
}
I follow this pattern every time I use threads in classes in MFC apps. That way I have the convenience of having all the members like I am in the class itself.

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