(* $Id: equeue.mli 41 2004-05-23 14:20:24Z gerd $ * * Event queues * written by Gerd Stolpmann *) (**********************************************************************) (*** ***) (*** Simple event handling ***) (*** ***) (**********************************************************************) (** [Equeue] implements generic event queues. An {b event system} * consists of an event queue, a list of event handlers, and an * event source. The queue has FIFO semantics, i.e. the first event * is processed next, and new events are appended to its end. When * an event is delivered to an event handler, all handlers are tried * until a handler accepts the event (or the event is dropped if no * such handler can be found). See below how a handler can indicate * whether to accept or reject an event. * * When the queue is empty, the event source is called once. The source * can add events to the queue, in order to continue event processing. * If the queue remains empty, the execution of the event system * stops. *) (** {b THREAD SAFETY} * * The module can be used in multi-threaded program provided no * event system is shared by several threads, or if so, access to * functions is serialized. *) (* CHECK: This is a bit hard, and Unixqueue does not serialize on * this level. Either weaken the condition, or make the module * really thread-safe. *) type 'a t (** This is the type of an event system with events of type 'a *) exception Reject (** May be raised by event handlers to reject events *) exception Terminate (** May be raised by event handlers to accept events while terminating * themselves *) exception Out_of_handlers (** Raised by [run] when the event source adds new events to the queue * but there are no event handlers to process them *) val create : ?string_of_event:('a -> string) -> ('a t -> unit) -> 'a t (** Creates a new event system that has an event source, but is * otherwise empty. The argument of type ['a t -> unit] is the * event source. The source can call [add_event] to put new events * into the queue. * * @param string_of_event Optionally, one can pass a printer for events. * This has only an effect for debugging output. *) val add_event : 'a t -> 'a -> unit (** Puts an event into the event queue of the system. *) val add_handler : 'a t -> ('a t -> 'a -> unit) -> unit (** Adds a handler to the list of handlers of the system. * * An event handler is called with the event system and the event as * arguments. The handler can return in various ways: * * - Return normally: This means that the event is accepted by the * handler. No other handler will be asked to process the event. * - Raise [Reject]: The event is rejected by the handler. The other * handlers are asked to process the event. * - Raise [Terminate]: The event is accepted, but the handler is * terminated, i.e. will never be called again. * - Raise another exception: The event is deferred, and will be * processed again in the future, but after the already queued events. * Furthermore, the exception falls through to the caller of * [run]. * * The handler can add new events and new event handlers. The latter * will be activated when the next event is processed. *) val run : 'a t -> unit (** Running a system means that, unless the queue is empty, the events * at the time of the [run] invocation and all later added events are * gone through. Each event is presented to the handlers until one * handler accepts the event. Events rejected by all handlers are * dropped silently. If there is no pending event the default event * source is called once. If there are still no events the system stops * and returns. If there are events to process but no handlers which * can do them all events are silently dropped, and the default event * source is called once. * * The exception [Out_of_handlers] is raised if there are events but no * handlers after the event source has been called. This is considered * as a programming error, and would cause infinite looping if not * detected. * * Note that there is an implicit order among the handlers which is * simply the order the handlers have been added to the system. This * means that you can set a fallback handler which catches any unprocessed * event by adding it last. * * Note that the events are processed in the order they happen. There * is no mechanism to assign priorities to events. * * Handlers are allowed to raise arbitrary exceptions. Exceptions other * than Reject and Terminate are not caught, so the caller has to do this * if appropriate. It is possible to restart an event system by just * calling [run] again. *) val set_debug_mode : bool -> unit (** Enables or disables debug mode. Output goes to stderr. *)