Event-Thread

Hey there,

does anybody know in which Thread, the ControllerListener is notified when a Controller is added/removed? In he AWT-Event-Thread?

I tried to figure it out by myself, by searching the cvs repo, but I cannot find a class which calls the ControlerEnvironment.fireControllerAdded/Removed methods.

Sorry, if my question is already answered in the JavaDoc, but I didn’t find an actual one. To be honest, I got the binaries from the LWJGL, since these were the most recent I found…

that’s right, it uses the JVM Event Thread Dispatcher. What is your problem? :slight_smile:

just to know, when/whether I need to synchronize.

I mean the AWT-Event-Thread is fine for most applications, but if

  • I write a console application, everything has to be executed by java.awt.EventQueue.invokeXXX to get rid of synchronization
  • I use another window kit (e.g. the Java GTK wrapper) there might be two different event-threads and I have to synchronize both

Or did I get s.th. wrong?

There are only 2 places that awt is involved in any jinput code, one is in the controller read test and the other is in the awt plugin. For normall applications using any of the native plugins, then no awt is present, unless you use the awt thread when you call poll or any of the other methods on jinput.

As for controller added/removed events, they are not implemented in any of the plugins as far as I am aware.

HTH

Endolf

A quick hunt through the code would show that there are a number of threads that jinput creates. A number of shutdown hook threads, so you should be able to ignore those. One of the windows plugins creates a thread, but that plugin is disabled by default, and the Linux plugin also creates one.
The linux one is due to the fact that you have to use the same thread for interactions with force feedback effects through out the life of the effect.

Other than those, any thread working in jinput is what ever thread you used to make the api call. All of the synchronisation should happen within the jinput code, so you should effectivly be able to treat it as a single threaded API. Should the controller listener events ever get fired, they will most likely happen as part of a call to poll, so will call back using the same thread you used to call poll again.

HTH

Endolf

Thanks for the information endolf,

That explains why I couldn’t find any calls to the methods firing events. :wink:

However, I wonder in which thread the events are dispatched, if implemented by a pulgin? (It’s in the API so, you probably have though about this)
IMO it should be consistent for all plug-ins, since one almost never uses them directly.

Beside removing the add/remove listener methods, the two solutions are:

  • A dispatch method should be added to the abstract ControllerEvironment class, which dispatches the events in the caller thread (compare to SWT). Of course the implementation should be thread safe, so it can be used from different ones.

  • A dedicated JInput Thread should run in the background, and the should be similiar synchronized static methods like provided by the java.awt.EventQueue. As a result, every Jinput code must be executed in this Thread (compare to AWT).

The latter one is clearly easier to implement, but more difficult to use. E.g. the user has to synchronize everything with the AWT-Event-Thread if using this window toolkit. Same with SWT, unless all SWT code is executed in the JInput-Event-Thread via the invokeXXX methods.

[update]
just read the previous post: dispatching in the poll method is similiar to the first and I good point is that when the polled controller removing is checked anyway for this one. On the other side, checking for all controller adds and removes within a poll, which is probaly done for each controller in each frame, is probably an overhead compared to a single call to dispatch, isn’t it?

An idea would be adding a callback interface to a newly added ControlEnvironment.dispatch method, which allows to poll the connected invidual controllers and optinally remove the method from the Control class.
[/update]

Just thoughts, I don’t need the events atm. :slight_smile:
And I kow that such things are difficult to implement correctly regarding threading, since I had to implment a firewire cameras, inclding listening to changes the bus…

Not to bring you to a wrong orientation, SYNCHRONIZING means to manage objects-accesses by the JVM, then it is quite clear that one accessed by one Thread shouldn’t be modified AT THE SAME TIME by another one. So we use SYNCHRONIZED clauses to LOCK access to an identified object while another one will WAIT FOR UNLOCKING. It is important to consider that another cannot wait for access unexplicitely, I mean, when it is called by a wait() or join(). Thus synchronized code would appear like:

//(somewhere in one Thread or Class)
synchronized (objectToLock) {
     // some code
    objectToLock.someMethod(); // this method can be a BLOCKING method
    // eventually call notfiy
    objectToLock.notify();
}

//(somewhere else in another Thread or Class)
synchronized(objectToLock) {
   // some other code
  // enventually call wait(): lock will be release waitin for a notice
  wait();
  // the very access to object 
 objectToLock.someMethod(); // this method can be BLOCKING too
}

That is the very most complex definition, while some dev’ers put a synchronized clause without checking for some blocking method.
To be clear, every synchronized clause grant that the encapsuled code is THREAD-SAFE, while it is still possible to crash on a freeze if the lock isn’t explicitely notified by a blocking method-call (i.e. (Object).wait(), (Thread)join(), and SOME other).
;D

Hi

We wouldn’t need to explicitly do a huge amount more work in some plugins. For example, direct input on windows will return an error code when we try and talk to the device if it is no longer there, and it’s a specific error code saying that the device is gone, so that returned error code could be checked for, and the event fired, all from within which ever thread you used to call poll(). Other platforms are not quite so easy, and neither is detecting new devices, however, I would still expect jinput to use your poll thread to report back to you, even if under the covers, we use our own. The simplest API is a single threaded one, and thats what I still believe we should be exposing to the users. It makes it easier to use JInput as you don’t have to worry about anything, you just know that when you call poll, other things under the covers may result in the events happening.

HTH

Endolf

I agree 100%.

My point was:
By adding a dispatchEvents() method to the ControllerEnvironment, the API still would be single threaded, since the listener callback would occur in the (single) thread calling this method and doing everything realted to JInput. The only difference/advantage would be, that it takes the controller-added (and optionally controller-removed) events out of the poll methods. Further, IMHO this indicates a single threaded API, but missing does the opposite. :slight_smile:
Note: If the plug-in dowsn’t support ControlListeners, as the existing ones, one could rely on a default behavior, e.g. throwing an UnsupportedOperationException.

Btw., another thing (not related to the above):
I don’t know about the the native plug-in apis, but I guess its not safe to poll a controller concurrently (from different threads or even VMs). Even if everything is thread-safe, one could miss state changes of ‘relative’ components. At least such problems occur with the native firewire APIs I worked with. I solved this by introducing some kind of a locking functionality in the API. Am I right that JInput ignores such a potential source of errors?

I theory I think most of the plugins it would be ok to call poll from a different thread to the one that initialised the plugin, but i’ve not tested it :slight_smile:

Yes, you are right that if you call poll from multiple threads, you will miss events on relative devices, once poll has been called, and the event queue read, the event is gone, another thread getting the events will get only those left on the queue. We’ll leave the one up to you to solve :slight_smile:

Endolf

again, thanks a lot for all the information endolf, really helpful :slight_smile: