Search code examples
javajna

Thread getting blocked in ReceiveNextEvent


Using JNA, I have built an api to receive OS events from Mac using Carbon framework. Now, there is a function in Carbon.framework defined as:

OSStatus ReceiveNextEvent (
ItemCount inNumTypes, //ItemCount is a 32-bit iteration count
const EventTypeSpec *inList, //EventTypeSpec is a structure
EventTimeout inTimeout,//EventTimeout is double-length integer of type EventTime
Boolean inPullEvent,
EventRef *outEvent
);

The documentation says this:

inNumTypes

The number of event types to wait for (0 if any event should cause this function to return). inList. The list of event types we are waiting for (pass NULL if any event should cause this function to return).

inTimeout The time to wait before returning (passing kEventDurationForever is preferred).  

inPullEvent Pass true for this parameter to remove the next matching event from the queue.

outEvent A pointer to the next event that matches the list passed in. If you passed true in the inPullEvent parameter, the event is owned by you, and you should release it when done.

Return Value A result indicating whether an event was received, the timeout expired, or the current event loop was quit. See “Carbon Event Manager Result Codes” (page 257) for possible values. Discussion

This function tries to fetch the next event of a specified type. If no events in the event queue match, this function will run the current event loop until an event that matches arrives, or the timeout expires. Except for timers firing, your application is blocked waiting for events to arrive when inside this function.

For the same, I have written the below in my JNA call:

NativeLong ReceiveNextEvent(NativeLong inNumTypes, EventTypeSpec[] inList,float inTimeout ,boolean inPullEvent, EdSdkLibrary.__EdsObject outEvent);

__EdsObject extends PointerType.

public static class __EdsObject extends PointerType {
    public __EdsObject(Pointer address) {
        super(address);
    }
    public __EdsObject() {
        super();
    }
};

EventTypeSpec is:
public class EventTypeSpec extends Structure {

    public int eventClass;
    public int eventKind;

    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"eventClass", "eventKind"});
    }
}

and call is as carbon.ReceiveNextEvent(new NativeLong(1), null, 1.0f, true, eventRef)

God knows why, but the thread doesn't come out of the statement. What is interesting, is that it does get events and dispatch them but doesn't come out. Has it got to do with the way I defined the function?


Solution

  • Your mapping is incorrect, and you are not providing an event structure into which the native code can write the event.

    NativeLong ReceiveNextEvent(NativeLong inNumTypes, EventTypeSpec[] inList, double inTimeout, byte inPullEvent, Pointer outEvent);
    

    You must provide a buffer in outEvent of sufficient size for the native code to write the event data (you were only providing an uninitialized pointer, thus the crash when your method signature was actually correct).

    The fact that you didn't crash with a float rather than double parameter is just happenstance. What actually happens is that all arguments prior to inTimeout get written to the wrong place in the stack, so your results are going to be undefined.

    I don't understand, however, why you're looking at the OS event queue for these events. According to the EDSDK documentation, events are sent to callbacks registered directly with the EDSDK library. I see no mention of the OS event queue in either the docs or the EDSDK sample code.