PDA

View Full Version : Implementing synchronous mechanism



Vagesh
25th November 2014, 13:36
Hi All,

I am developing a dll which will be exposing some API's like Login,Logout. This dll will be talking to another component(Say Engine) over the socket in the form of XML Request and Response messages.
e.g. Suppose Dll sent the Request like LoginRequest then that another component will respond with LoginResponse and some more message like LoginStatusEvent etc..
Also this component keeps on sending different messages which are not related to LoginRequest

So I am looking for implementation where dll will send the Request and will wait with the help of QWaitCondition.wait() maximum for let's say 15 sec and before this timeout if LoginResponse & LoginStatusEvent received from the socket then it will raise QWaitCondition::wakeup() so that it will wakeup and process the messages.

This dll will be consumed by any application which will invoke the API's and to avoid second time invocation and to respond with proper success or failure of the request I want to keep this as a blocking call.

Currently in my dll i do not have any thread and Socket Communication is happening using QTCPSocket.

I can not create the socket in QThread::Run() because all the request's are come from GUI API call.

So please guide how i can implement this.

Thanks in advance.

wysota
25th November 2014, 13:59
I would use a QEventLoop to block the flow until you decide to quit the queue.

anda_skoa
25th November 2014, 14:05
I can not create the socket in QThread::Run() because all the request's are come from GUI API call.

How does calls coming from the GUI make it impossible to create objects in the worker thread?

Cheers,
_

Vagesh
25th November 2014, 14:29
Following is the existing flow.

1. From GUI StationLogin() API is invoked.
2. The Dll creates the API into XML message
3. DLL send this XML message over the socket to the other component.
4. That component process that message and respond with some more xml messages and actual response.

So in step 3 socket object is used to send the messages and step 4 is used the same object to receive the messages.

So If i create the socket object in QThread::Run() then I will not be able to use it in step 3.

Vagesh
25th November 2014, 17:07
I would use a QEventLoop to block the flow until you decide to quit the queue.


Hi Wysota,

QEventLoop resolves my requirement. Thanks a lot for your help.


QEventLoop loop;

connect(this,SIGNAL(ComeOutOfEventLoop()),&loop,SLOT(quit()));
loop.exec();

and whenever i receive specific message I am sending

emit ComeOutOfEventLoop();

I will be also adding timer based quit. So that after specific time automatically loop will get quit.


In Some of article I read that Using QEventLoop is not safe. I did not get why.
I think if I exit from this event loop then there should not be issue.

Let me know your thoughts.

anda_skoa
25th November 2014, 17:30
Following is the existing flow.

1. From GUI StationLogin() API is invoked.
2. The Dll creates the API into XML message
3. DLL send this XML message over the socket to the other component.
4. That component process that message and respond with some more xml messages and actual response.

So in step 3 socket object is used to send the messages and step 4 is used the same object to receive the messages.

So If i create the socket object in QThread::Run() then I will not be able to use it in step 3.

I don't see why not.

How does using a socket for receiving data make it impossible to use it for sending data?

I have done that more often than I could count.
It used to be the main pattern for thread based socket communication until QTcpSockets could safely be moved to a different thread.



In Some of article I read that Using QEventLoop is not safe. I did not get why.
I think if I exit from this event loop then there should not be issue.

It can lead to unexpected re-entrancy.
Code containing a nested event loop looks like a blocking call from outside but it isn't.

Cheers,
_

wysota
25th November 2014, 18:28
Hi Wysota,

QEventLoop resolves my requirement. Thanks a lot for your help.


QEventLoop loop;

connect(this,SIGNAL(ComeOutOfEventLoop()),&loop,SLOT(quit()));
loop.exec();

and whenever i receive specific message I am sending

emit ComeOutOfEventLoop();

I will be also adding timer based quit. So that after specific time automatically loop will get quit.


In Some of article I read that Using QEventLoop is not safe. I did not get why.
I think if I exit from this event loop then there should not be issue.

Let me know your thoughts.
Basically you should know what you are doing. The point is to not enter the same loop more than once. If you have an event loop as an automatic (local) variable then you should be safe. In your case if you don't launch a login process before finishing the previous one it'll be alright.

Vagesh
26th November 2014, 07:39
I don't see why not.

How does using a socket for receiving data make it impossible to use it for sending data?

I have done that more often than I could count.
It used to be the main pattern for thread based socket communication until QTcpSockets could safely be moved to a different thread.


It can lead to unexpected re-entrancy.
Code containing a nested event loop looks like a blocking call from outside but it isn't.

Cheers,
_


Thanks a lot anda_skoa for your response.

Currently in my program there is no any thread. So if I put the thread on sleep using QWaitCondition.Wait() then my thread is getting block and I also observe that data is also not able to read from the socket.

Please guide me who I can resolve this issue.

wysota
26th November 2014, 09:04
If you want to use wait conditions then obviously you will need a thread that will perform the operation while the main thread is blocked. That extra thread will need an event loop running (or an equivalent -- using waitFor* family of functions). So you will have to use an event loop either way, it is up to you whether you want it to be in an extra thread or in the main thread using QEventLoop.

anda_skoa
26th November 2014, 10:26
Currently in my program there is no any thread.

That contradicts what you wrote earlier.
If there is no additional thread, then there is no Thread::run() method that you have implemented and have tried to create a socket in.

Cheers,
_

Vagesh
27th November 2014, 07:44
If you want to use wait conditions then obviously you will need a thread that will perform the operation while the main thread is blocked. That extra thread will need an event loop running (or an equivalent -- using waitFor* family of functions). So you will have to use an event loop either way, it is up to you whether you want it to be in an extra thread or in the main thread using QEventLoop.

Ok, So initially there is no any thread only signle thread which is MainThread. But to achieve my task I tried to implement the threading mechanism where I observed that when i use QWaitCondition.Wait() it is also blocking m_pSocket from reading the data from the socket.

wysota
27th November 2014, 08:50
If you don't need threads then don't try to force yourself to use them.