Event Queue Module specification for the Reactor pattern
The event queue module exists for the purpose of maintaining an event queue and running an event loop based on that queue.
The "reactor" top-level module must export enterEventLoop, enqueue, shutdown, hasPendingEvents, processNextEvent, and optionally getNextEvent.
- Enters the event loop, sequentially processing each event in the queue and blocking (waiting) for events when the queue is empty. This should continue to loop until shutdown is called and all the events are processed. If a function is provided as the first parameter, it should be called after any event finishes processing and the queue is empty.
- enqueue(task, priority) boolean
- Adds a new event to the event-queue. The first parameter, task, should be a function that will be added to the queue and then executed when its is removed from the queue. The second parameter is a number that indicates the requested priority of the task. The handling of the priority parameter is implementation specific and it may be ignored. This returns true if the task was successfully added the queue, otherwise it should return false (generally only the case if the event loop is shutting down).
- This makes a request to exit the event loop. The event loop will continue processing all the events in the queue, but the enqueue operation should not allow any events to be added. One the event loop has processed all the events in the event queue, enterEventLoop should return.
- Determines whether or not the event-queue has events that are ready to be processed. Returns true if there are pending events at the time the function was called.
- Processes the next pending event. If there aren't any pending events, this method may wait -- depending on the value of the mayWait parameter -- until an event is enqueued in this queue. This method is re-entrant. If the mayWait parameter is true, this method blocks until an event is available to process if the event queue is empty. If false, this method returns immediately if the queue is empty. This returns true if an event was processed, or false if there were no pending events.
- If implemented, this returns the next event function to be processed, removing it from the queue. this method blocks until an event is available if the event queue is empty.
- timer setTimeout(func, delay, context, ...param)
- Schedules a one shot timer to execute the passed function after "delay" milliseconds. If "context" is passed, the function will be bound to it when invoked. Any additional parameters should be curried and passed as params to the function as well. This method does not offer a real-time guarantee. The passed function will execute eventually but it may be delayed if the process is busy executing other code in the mean time. Returns an opaque object referencing the scheduled timer.
- void clearTimeout(timer)
- Removes a previously scheduled one-shot timer from the event loop. If the passed timer object is not valid or if it has already fired, this function has no effect.
- timer setInterval(func, delay, context, ...param)
- Works just like setTimeout() with the same params except the function will execute periodically every "delay" milliseconds until the timer is explicitly cancelled.
- void clearInterval(timer)
- Removes a previously scheduled interval timer from the event loop. If the passed timer is not a valid interval timer or if it has already been cancelled, this function has no effect.
- If a timeout timer or an interval timer is scheduled, should the process exit when the main code finishes executing? If so, how do we blend that with the event-drive API of the browser or node.js where you run an implicit event loop? A generic wait() function won't work because you can't actually block in the browser. [Charles Jolley]
- The browser does not support explicit control over it's event loop. This means you pretty much cannot implement any of the above methods except for enqueue(), setTimeout(), clearTimeout(), setInterval(), and clearInterval(). Perhaps the loop control methods should be made optional? [Charles Jolley]