PDA

View Full Version : Queuing QMetaObject::invokeMethod



yagabey
15th March 2017, 23:53
Hello,

I want to distribute requests from a system to a limited number of threads. I can run a request on the thread using signals/slots or QMetaObject::invokeMethod function. But I also want to buffer the incoming requests for running them later when a thread becomes available.

For example I have a function call like:


QMetaObject::invokeMethod(worker, "queryCustomCommand", Q_ARG( qint64 , trans ) ,Q_ARG( QString, sql ));

or :

QMetaObject::invokeMethod(worker, "getTagLastChangeTime", Q_ARG( pQueryValueRequest_t ,req ) ,Q_ARG( qint64, trans ));


These should be buffered in an appropriate way.
I tried to create a list of struct representing the method and arguments. But I couldnt find a way to represent the Q_ARG vars in the struct:


struct StackItem{
char* methodName;
QList<QGenericArgument> argList;
};

Here I couldnt form the "argList" element.(Compile errors, etc...)
What is the right way of queuing these function calls?

Thanks in advance,
Yigit

yagabey
16th March 2017, 09:14
I figured out that I can queue arguments in that form:


StackItem stim;
QGenericArgument gar1 = Q_ARG( qint64 ,trans );
QGenericArgument gar2 = Q_ARG( QString, sql );
stim.argList.append(gar1);
stim.argList.append(gar2);
stim.metname = "queryCustomCommand";


But when i call :


QMetaObject::invokeMethod(worker, stim.metname.toLocal8Bit().data(), stim.argList.at(0) , stim.argList.at(1));


works correctly most of the time. But sometimes sends some wrong and unmeaningful parameters to thread. And sometimes crashes.

Any idea?
Thanks..

anda_skoa
16th March 2017, 12:32
I am wondering if you would not be better of using a threadpool and delegating tasks to it.

See QThreadPool.

Cheers,
_

yagabey
16th March 2017, 12:54
Thanks Anda,

The problem is that my classes are not inherited from QRunnable.
I am just moving them into thread and adding to a watch list:


ProjectDatabase *worker = prepareDbConnection();
QThread* thread = new QThread;
worker->moveToThread(thread);

I havent used QThreadPool before. I think my worker class should inherit from QRunnable. That may change lots of things in my code.

I mainly have a constant number of database connection threads. I want to keep these connections active. And I am keeping track of which connections are available for new queries. When a query or a custom request arrives , I am directing the query to that connection.

Is it possible to achieve this without changing too much things or I should port everything to Qthreadpool, Qrunnable domain?

anda_skoa
17th March 2017, 09:35
Ah, I see, that isn't a very good fit for a QThreadPool and you are basically implementing your own similar mechanism.

However, I am wondering if you could not do a similar task queue.

Usually a thread pool worker runs like this

1) start up and initialization: here yours would open the database connection
2) wait on a task queue
3) if a task is enqueued, dequeue it and process it
4) repeat at 2

The data entry structure in a custom task queue can be anything you want.

Depending on whether the worker's run an explicit loop or an event loop the queue wait would either be e.g. a QWaitCondition wait or the event loop idling and waiting for a signal.

Cheers,
_