PDA

View Full Version : Plesase help ! Qt plugins and Threads



berzeck
21st May 2010, 21:39
Hello every one, i have a problem with plugins :

I am programming a server that accepets tp connections, for each incomming connection, the server generates a new thread.
Each thread has to load the same physical plugin (libAuthcomPassword.so is the name of the file )
The idea is that each thread create a different instance of the plugin
In each thread, i load the plugin with this command
<code> QPluginLoader loader (directory );
QZPlugInterface* authenticatorIfc = qobject_cast< QZPlugInterface*> ( loader.instance() )
</code>
Debugging the program i noticed that the instance 'authenticatorIfc' has the same address in every thread (thus the same instance) so the program crashes (becasuse different threads tries to execute the same instance of the object )

How can i load the same physical plugin, but different instaces ?
Thank you very much

PD: sorry my bad english :$

tbscope
21st May 2010, 21:44
Why do you design a space shuttle to go to the grocery?
In other words: keep it simple, it'll save you loads of time.

Why do you need threads?

squidge
21st May 2010, 21:52
You only need the DLL loaded once (and even if you try and loaded more than once, the OS will ignore you)

You only need one thread.

KISS (http://en.wikipedia.org/wiki/KISS_principle)

berzeck
21st May 2010, 22:00
hi, thanks for answering, this is the thing
The server "processes action-request" from the clients codified in a XML language, for example :
<ActionRequest RequestID = "134454">
<DBInsert>
<InsertTable>table1</InsertTable>
<InsertFields>field1, field2</InsertFields>
<InsertValues>1|1</InsertValues>
<InsertValues>2|rew</InsertValues>
<InsertValues>3|r4few</InsertValues>
</DBInsert>
</ActionRequest>

Introduces 3 records to the database.
The parser that translates the XML to proper sql query is implemented as a plugin ( so i can add a lot of functionality without modifying the core ), the idea is that each connection creates an instances of this parser so a resource-intense activity wouldn't freeze other requests from other clients
Each incoming client also establish a different connection to the database so this is also threaded

Thanks

berzeck
21st May 2010, 22:02
fatjuicymole, thanks for answering, i dont have a problem to have the plugin loaded once, but what i need is that the plugin generates different instances in different addresses, so each thread have a differente instance of the same class.

squidge
21st May 2010, 22:59
If you attempt to load a DLL more than once, you will always be given the same address.

You can handle all your connections in a single thread, therefore you only need one thread. So a single instance of the DLL is not a problem.

Multiple threads are only required if you are running the cpu under heavy load so you can share the load between multiple cores.

berzeck
21st May 2010, 23:13
Suppose that i am importing a database from the client that has 1000000 rows
the parser will take a little to parse the xml format (of course my program divides it in packets and i read the xml as a stream), if its in a single thread then it will freeze others requests becasue the parser will have to read and parse 1000000 rows before attending other requests
the server also can perform calculations on each field of each row if you want, for example : convert the currency field to another currency
so the idea is that no client freezes
i would call that heavy load

some ideas ?
thanks again

wysota
21st May 2010, 23:42
the parser will take a little to parse the xml format (of course my program divides it in packets and i read the xml as a stream), if its in a single thread then it will freeze others requests becasue the parser will have to read and parse 1000000 rows before attending other requests
the server also can perform calculations on each field of each row if you want, for example : convert the currency field to another currency
so the idea is that no client freezes
i would call that heavy load

I would still do it in one thread and optionally delegate the long tasks to other threads (i.e. using QtConcurrent) keeping the main processing in one thread only.
If you insist on having multiple threads then you need to treat your plugin as a factory able to create instances of classes that provide the actual functionality you want.

But again, I'd do it in one thread. The "plugin" itself can internally use many threads.

berzeck
21st May 2010, 23:43
I guess I finally found a nice workaround to solve my problem.
I simply declare the following function in the
interface

QObject* createInstance();

the implementation would be :

return new PluginClass();

Now all the functionality can be implemented in this one plugin class
that directly inherits from the interface and I am able to get multiple
objects of this class by call createInstance().

thanks for trying to help me :)

wysota
22nd May 2010, 00:25
I guess I finally found a nice workaround to solve my problem.
I simply declare the following function in the
interface

QObject* createInstance();

the implementation would be :

return new PluginClass();

Now all the functionality can be implemented in this one plugin class
that directly inherits from the interface and I am able to get multiple
objects of this class by call createInstance().

It's called a factory and exactly what I was talking about.

But I still think you are urging to shoot yourself in the foot (http://www.fullduplex.org/humor/2006/10/how-to-shoot-yourself-in-the-foot-in-any-programming-language/).

berzeck
24th May 2010, 19:56
Hi Wysota, thanks for answering.
The idea is that each connection has not only its own thread, but it's own space address, there is no information shared between threads, so the case you were pointing out would not happen
The only data that gets out of the threads are database connections and a limited number of signals sent to the connection server to update real time information

wysota
25th May 2010, 08:43
The idea is that each connection has not only its own thread, but it's own space address,
This is contradictory. Threads are in essence (light) processes that share address space. If you want separate address spaces, you have to do it with processes not threads.


there is no information shared between threads, so the case you were pointing out would not happen
What case? I don't think I was pointing any case :)

berzeck
26th May 2010, 21:04
I mean that the objects created in each thread are in separated addresses, i agree that the threads themselves share address space, in my case these objects are the parsers and processes

So the requests the client sends to the server should be processed in separates threads ( each client has his own process address space )

So, for example is the request is to retrieve thousands of records ( inventory kardex report for example ), it wont freeze other request from other clients

I was pointing out the example on the page you linked in your comment

Do you have another idea how to implement this ?

squidge
26th May 2010, 22:01
This is how I would probably do it: (I say probably, as I normally have to write 100+ pages of documentation stating what I'm doing and why I'm doing it before writing a single line of code, and then go under review with other engineers and blah blah lots more boring stuff)

ConnectionManager: Handles all the connections in asynchronous mode. This would be a single thread, and as such, would be the only thread accessing the authentication dll, etc.
RequestManager: Would take requests from the connection manager and processes them. By default only a single thread is used, but if another request comes in whilst that thread is busy, another thread would be created to handle the load, upto the maximum number of threads configured. The idea here is so you could have 1,000 connections but not be too resource heavy depending on hardware and OS, as it's unlikely that all 1,000 connections will be busy processing at all times, and even if so, the performance would likely be too slow with 1,000 threads all processing data. Threads would be deleted after an idle time, but a minimum amount would be kept depending on configuration.
etc...

wysota
26th May 2010, 23:07
So the requests the client sends to the server should be processed in separates threads ( each client has his own process address space )
You can have two instances of the same class in the same thread, you know...


QString one;
QString two;


So, for example is the request is to retrieve thousands of records ( inventory kardex report for example ), it wont freeze other request from other clients
So delegate fetching the data to another thread. You don't have to do everything in another thread. You can have one object that acts as a manager and this manager spawns threads to do particular jobs.


I was pointing out the example on the page you linked in your comment
I still stand by the statement that you are trying to shoot yourself in the foot.

I agree with what fatjiucymole suggests, I would do it in a more or less similar way. Actually I implemented something like this few days ago for parallel processing of multiple nested sql queries using QtConcurrent.

berzeck
27th May 2010, 08:28
One question, i understand that widgets must live in the main thread, can i set a model to a view that lives in a different thread ?
If the answer is no ( i really don't know) then how can a fill my model with data using a separate thread ?
Obviously i am no expert and i want to learn, thank you

wysota
27th May 2010, 08:35
One question, i understand that widgets must live in the main thread, can i set a model to a view that lives in a different thread ?
Technically you can but unless you protect direct access with mutexes, this is bound to explode sooner or later.


If the answer is no ( i really don't know) then how can a fill my model with data using a separate thread ?
Using signals and slots.

berzeck
27th May 2010, 08:43
so if i have 100000 records parsed in a different thread, then i send a signal for each row 100000 times to fill the model ?

Because if i send one signal with all the data, the main thread would freeze filling the model with 100000 rows (since we are assuming that the model is living in the main thread with the view )

tbscope
27th May 2010, 09:41
No you send a signal every few seconds or every 1000 records, depending how long it takes to parse one record