It seems that according to the specification there's a race condition between the clEnqueue* functions and clSetEventCallback. In other words, it seems that the implementation is allowed to start execution of enqueued commands at any point. So this means that if client is to register callbacks in the event object received from the call to clEnqueue there's a race condition between the actual execution and the event registration.

The way I see this is that the race condition exists because a) queue can start processing at any time
b) event callbacks are edge-triggered as opposed to level-triggered.

The registered callback function will be called when the execution status of command associated with event changes to an execution status equal to or past the status specified by command_exec_status
The way I read this is that the callbacks will be fired on state change. Thus if state has already changed before a callback is registered the callback won't fire.

So how is the client code supposed to use the callbacks safely?