AndreasFagschlunger / O2Xfs

Java API for accessing CEN/XFS API, EMV Level 2 Kernel
47 stars 28 forks source link

Blocking behavior of EventDispatcher #42

Closed PouyaMoradian closed 7 years ago

PouyaMoradian commented 7 years ago

Hi @AndreasFagschlunger

As I had a refactoring on my code and removing the TCP/IP layer that I was implemented over O2, I was facing some problem with the EventDispatcher class, when I receive an event and on the handler method I call another method that uses O2 info command like status and etc, the answer of this info command will be missed and the request will be on an infinite wait (with time out of 0), so I put a new thread to the callback method of XfsServiceManager for eventDispatcher.dispatch(...) to prevent this kind of problem.

please correct me if it may cause some new problem, and also if you have a better solution for this problem.

with regards, Pouya Moradian

AndreasFagschlunger commented 7 years ago

Hi @pouyamoradian

Indeed, EventDispatcher calls XfsEventNotification methods directly. So if you're executing a command in a method of XfsEventNotification and wait for the result at the same time, the thread is blocked.

ReadCardCommand uses EventQueue class to workaround this problem. It may also be possible to implement a EventQueue for EventDispatcher directly. The main reason I didn't was unexpected behavior. Take for example EjectCardCommand. You asynchronously execute a EJECT_CARD command. You wait for the asynchronous result and then wait for a MEDIAREMOVED service event.

If you have a EventQueue, the MEDIAREMOVED may reach you before the WFS_EXECUTE_COMPLETE event. So you may end up waiting for a card to take which has already be taken. One future improvement might be, to use one Thread per Service. But then again, if you query the same service (which is likely) during event processing, the thread is blocked.

So the framework doesn't restrict you to use event queues but you should carefully think about where to use them. I try to use a state machine in cases like this. Again, EjectCardCommand for example. There is one Thread who issues the command and waits for results. Event processing in general should be fast and simple, so I only try to change the state and notify the waiting thread about the state change (e.g. EjectCardCommand.cardTaken()). EventDispatcher thread is released and I'm free to call the next command within my command thread.

I hope the answer fits your needs,

Best regards, Andreas Fagschlunger