Module eventer
The eventer is an event dispatcher.
It works on top of Copas Timer using the
worker
to create event handlers. The eventer uses a publish/subscribe mechanism with servers and clients.
The servers should register before firing any events, and the clients should
subscribe to server events.
Dispatching pushes event data in the worker
queues of the eventhandlers. This means that one or more workers
have been scheduled to each handle one or more enqueued events, but they will not be executed when an event
is dispatched. Execution follows later when
the Copas Timer loop continues to handle its worker queues in the background.
The events have 2 synchronization methods; finish and waitfor .
The eventer will create a table within the Copas module; copas.eventer
, but that
should generally not be used except for
the copas.eventer.decorate
method which will provide an object/table with event capabilities.
Info:
- Copyright: 2011-2014 Thijs Schreijer
- Release: Version 1.0, Timer module to extend Copas with a timer, worker and event capabilities
- License: Copas Timer is free software under the MIT/X11 license.
- Author: Thijs Schreijer, http://www.thijsschreijer.nl
Class event_server
event_server.events | Table (as a set) with the event strings for this server. |
event_server:dispatch (event, ...) | Dispatches an event for this server. |
event_server:subscribe (client, handler, event) | Subscribes a client to the events of this server. |
event_server:unsubscribe (client, event) | Unsubscribes a client from the events of this server. |
Class event
event.queueitems | Table/list with queueitems created. |
event:cancel () | Cancels all event related queueitems from the Copas background worker queues. |
event:finish (timeout) | Waits for an event to be completed in a blocking mode. |
event:waitfor (timeout) | Waits for an event to be completed in a non-blocking mode. |
Eventer core functions
clientsubscribe (client, server, handler, event) | Subscribes a client to events. |
clientunsubscribe (client, server, event) | Unsubscribes a client from events. |
decorate (server, events) | Decorates an object as an event server. |
getclients (server) | Gets a list of clients of a particular server. |
getsubscriptions (client) | Gets a list of subscriptions of a particular client. |
serverdispatch (server, event, ...) | Dispatches an event from a server. |
serverregister (server, eventlist) | Registers a server that will fire events. |
serverunregister (server) | Unregisters a server that will no longer fire events |
seterrorhandler (handler) | Sets the error handler function to be used when calling eventhandlers. |
Eventer and Copas events
copas.eventer.events | Event generated by the eventer. |
copas.events | Events generated by Copas. |
Class event_server
This class describes the elements applied to an event server by the decorate function- event_server.events
-
Table (as a set) with the event strings for this server. The set generated is
protected, so accessing a non-existing element will throw an error.
See also:
Usage:
-- create an object and decorate it with event capabilities local obj1 = {} copas.eventer.decorate(obj1, { "start", "error", "stop" } ) print(obj1.events.start) --> "start" print(obj1.events.error) --> "error" print(obj1.events.stop) --> "stop" print(obj1.events.not_found) --> throws an error
- event_server:dispatch (event, ...)
-
Dispatches an event for this server. It functions as a shortcut to
serverdispatch .
Parameters:
- event string one of the elements of event_server.events indicating the event to dispatch
- ... any additional event parameters
Returns:
See also:
Usage:
-- create an object and decorate it with event capabilities local obj1 = {} copas.eventer.decorate(obj1, { "start", "error", "stop" } ) ..... do some stuff, subscribe to events, start the copas loop, etc. -- raise the start event and include th starttime as an extra -- parameter to be passed to the eventhandlers local e = obj1:dispatch(obj1.events.start, socket.gettime()) -- now wait for the event to be completely handled e:waitfor()
- event_server:subscribe (client, handler, event)
-
Subscribes a client to the events of this server. It functions as a shortcut
to clientsubscribe . See the example below for the format of the
event data delivered to the event handler.
Parameters:
- client the client identifier (usually the client object table)
- handler function the handler function for the event. For the function signature see clientsubscribe .
- event
string
the event (from the list event_server.events ) to subscribe to or
nil
to subscribe to all events
See also:
Usage:
-- create an object and decorate it with event capabilities local obj1 = {} copas.eventer.decorate(obj1, { "start", "error", "stop" } ) -- create another object and subscribe to events of obj1 local obj2 = { eventhandler = function(self, eventqueue) while true do local event = eventqueue:pop() -- handle the retrieved data here print(event.client) --> "table: 03AF0910" == obj2 print(event.server) --> "table: 06A30AD3" == obj1 print(event.name) --> "stop" print(event.n) --> "2" print(event[1]) --> "arg1" print(event[2]) --> "arg2" end end, } obj1:subscribe(obj2, obj2.eventhandler, obj1.events.stop) ..... do some stuff, start the copas loop, etc. -- raise the stop event local e = obj1:dispatch(obj1.events.stop, "arg1", "arg2")
- event_server:unsubscribe (client, event)
-
Unsubscribes a client from the events of this server. It functions as a shortcut
to clientunsubscribe .
Parameters:
- client the client identifier (usually the client object table), must be the same as used while subscribing.
- event
string
the event (from the list event_server.events ) to unsubscribe from or
nil
to unsubscribe from all events
See also:
Class event
Class returned for a dispatched event, with synchonization capabilities- event.queueitems
- Table/list with queueitems created. One for each event subscription dispatched.
- event:cancel ()
- Cancels all event related queueitems from the Copas background worker queues. Queueitems will remain in the event object itself, but will be flagged as cancelled.
- event:finish (timeout)
-
Waits for an event to be completed in a blocking mode. That is; all event queueitems have been completed by the workers
(this does not include additional events spawned from them). Current thread will
NOT yield while waiting, it will only process the event related queueitems. It is blocking, so timers, sockets
and workers will not run in the mean time, so executing this method may take a long time so use carefully!
If it should not block, then use event:waitfor .Parameters:
- timeout
timeout (in seconds), use
nil
for no timeout
Returns:
true
when completed, ornil, "timeout"
in case of a timeout (in case of a timeout, the unfinished queueitems will remain in the worker queues, they will not be cancelled).See also:
- timeout
timeout (in seconds), use
- event:waitfor (timeout)
-
Waits for an event to be completed in a non-blocking mode. That is; all event queueitems have been completed by the workers,
this does not include additional events spawned from them. Current thread/worker will
yield while waiting (so cannot be used from the mainthread!).
Parameters:
- timeout
timeout (in seconds), use
nil
for no timeout
Returns:
true
when completed, ornil, "timeout"
in case of a timeout.See also:
- timeout
timeout (in seconds), use
Eventer core functions
Generally these functions are not used, except for decorate which implements regular object oriented access to all others.- clientsubscribe (client, server, handler, event)
-
Subscribes a client to events.
The prefered way is to use the decorate function and then call event_server:subscribe .
Parameters:
- client unique client parameter (usually self)
- server a unique key to identify the specific server (usually the server object/table)
- handler
event handler function to be called, it will be wrapped as a background worker-coroutine. If
client
is either a table or a userdata (object types), then the handler will be called with 2 arguments;client
andworker
, otherwise it will only getworker
. See event_server:subscribe for an example of how the parameters are passed to the handler. - event
string
event name, or
nil
to subscribe to all events
See also:
- clientunsubscribe (client, server, event)
-
Unsubscribes a client from events.
The prefered way is to use the decorate function and then call event_server:unsubscribe .
Parameters:
- client unique client parameter (usually self)
- server
a unique key to identify the specific server (usually the server object/table), or
nil
to unsubscribe from all servers - event
string
event string, or
nil
to unsubscribe from all events
See also:
- decorate (server, events)
-
Decorates an object as an event server. It will provide the object with the
following methods/tables; Additionally it will register the object as event server. The methods are
shortcuts to the eventer methods
clientsubscribe, clientunsubscribe, serverdispatch
. See event_server for some examples.Parameters:
- server The event server object that will be decorated with the methods and tables listed above.
- events
A list of event strings (see event_server.events ). This list will be copied to a new table (as a set) and stored in
server.events
See also:
- getclients (server)
-
Gets a list of clients of a particular server.
Parameters:
- server the server for which to get the subscribed clients
Returns:
nil
if the server is unregistered, otherwise a table with subscriptions. The result table is keyed by 'event string' and each value is a list of clients that is subscribed to this event.Usage:
local list = copas.eventer.getclients(copas) -- get list of Copas clients list = list[copas.events.loopstarted] -- get clients of the 'loopstarted' event print ("the Copas 'loopstarted' event has " .. #list .. " clients subscribed.")
- getsubscriptions (client)
-
Gets a list of subscriptions of a particular client.
Parameters:
- client the client for which to get the subscriptions
Returns:
nil
if the client has no subscriptions, otherwise a table with subscriptions. The result table is keyed by 'server' and each value is a list of eventstrings the client is subscribed to on this server. - serverdispatch (server, event, ...)
-
Dispatches an event from a server.
The prefered way is to use the decorate function and then call event_server:dispatch
Parameters:
- server a unique key to identify the specific server
- event string event string
- ... other arguments to be passed on as arguments to the eventhandler
Returns:
See also:
- serverregister (server, eventlist)
-
Registers a server that will fire events.
The prefered way is to use the decorate function.
Parameters:
- server a unique key to identify the specific server. Usually a table/object, but can be a string or whatever, as long as it is unique
- eventlist list of strings with event names (table keys are unused, only values, so may also be a set)
See also:
- serverunregister (server)
-
Unregisters a server that will no longer fire events
Parameters:
- server a unique key to identify the specific server
- seterrorhandler (handler)
-
Sets the error handler function to be used when calling eventhandlers.
to an xpcall call)
Parameters:
- handler the error handler function (the errorhandler will be passed along
Eventer and Copas events
List of events as generated by Copas and the Eventer itself, once the eventer module has been loaded.- copas.eventer.events
-
Event generated by the eventer.
Fields:
- register Fired whenever a new server registers events (note: 'copas' and 'copas.eventer' will have been registered before any client had a chance to subscribe, so these subscriptions cannot be caught by using this event)
- unregister Fired whenever a server unregisters its events
- subscribe Fired whenever a client subscribes to events
- unsubscribe Fired whenever a client unsubscribes from events
- copas.events
-
Events generated by Copas. The event structure for Copas will only be
initialized when the eventer is used.
Fields:
- loopstarting Fired before the copas loop starts. It will immediately be finished (see event:finish ). So while the event threads run there will be no timers, sockets, nor workers running. Only the threads created for the 'loopstarting' event will run.
- loopstarted Fired when the Copas loop has started, by now timers, sockets and workers are running.
- loopstopping
Fired when the Copas loop starts exiting (see
exitloop
). For as long as not all event threads (for this specific event) have finished, the timers, sockets and workers will keep running. - loopstopped Fired after the Copas loop has finished, this event will immediately be finished (see event:finish ), so the timers, sockets and workers no longer run.
See also: