The event-glue Reference Manual

Table of Contents

Next: , Previous: , Up: (dir)   [Contents][Index]

The event-glue Reference Manual

This is the event-glue Reference Manual, version 0.1.0, generated automatically by Declt version 2.3 "Robert April" on Wed Mar 14 03:51:51 2018 GMT+0.


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

event-glue: simple eventing abstraction

event-glue is a library that offers simple abstraction around event processing. It's goal is to be compact, performant, extendable, and make no assumptions about your eventing infrastructure. It currently has no dependencies.

It is used in turtl-core to provide the main fabric of communication between various pieces of the app. It can be used anywhere you need a generic event handling system.

Why?

Eventing can be a great way to organize code.

Let's say you have an app. This app has a view (HTML, GTK, whatever). That view has a button. When the button is clicked, you have to run three different functions: launch-nuke, notify-president, lock-fallout-shelter. Now let's say you need to add another view to your app. This view also has a button, that when pressed, needs to do some things specific to that particular view, as well as run your three functions from earlier.

You can do a few things:

  1. Duplicate the calls to the launch-nuke, notify-president, and lock-fallout-shelter. After all, it's only three functions, right? Well if you need to add another function to call later, you have to remember to update all the places that call your function set.
  2. Abstract the functions calls inside of another function. This is a fine solution, but can end up giving you weird trees of functions that do similar things.
  3. Use eventing. Instead of calling your functions directly, you create and trigger a new event "red-button-pressed." Then you set up bindings to that event which tie the firing of the event to the specific actions that need to be called when it's fired. This offers strong decoupling of your interfaces. Instead of the button needing to know what to run, it just fires an event and each function is responsible for acting on it.
(defun launch-nuke (ev) ...)
(defun notify-president (ev) ...)
(defun lock-fallout-shelter (ev) ...)

(bind "red-button-pressed" 'launch-nuke)
(bind "red-button-pressed" 'notify-president)
(bind "red-button-pressed" 'lock-fallout-shelter)

(defun red-button-pressed ()
  (trigger (event "red-button-pressed")))

The next time we add a red button to another interface, all we have to do is run the same trigger: (trigger (event "red-button-pressed")) and our functions will fire automatically.

You can use eventing as much or as little as you want...your entire application can be based on cascading triggering of events or you can just use it for simple one-off cases. Either way, it can be a useful tool for just about any project.

How?

event-glue can be used two ways:

  1. Globally triggering events on your whole app
  2. Triggering events on specific objects

Global triggering:

;; when the database is finished initializing, apply our schema
(bind "db-init" apply-schema)

;; initialize the db, triggering "db-init" when done
(init-my-db :when-finished (lambda () (trigger (event "db-init"))))

Triggering on specific objects:

;; create our own class that extends `dispatch`
(defclass user (dispatch)
  ((name :accessor name :initarg :name :initform "slappy")))

;; create the user and bind to its "login" event
(defparameter *user* (make-instance 'user))
(bind "login" (lambda (ev) (format t "user ~a logged in~%" (car (data ev)))) :on *user*)

;; show our fictional interface, and once they login, trigger our event
(show-login :login-cb (lambda (username password)
                        ;; forward the username/password to our bindings via
                        ;; the event `:data` keyword
                        (trigger (event "login" :data (list username password))
                                 :on *user*)))

API

dispatch (class)

dispatch is an opaque class. It is an object that matches events to event bindings. All event bindings live in a dispatcher, and all events that are triggred are triggered on a dispatcher. It is the backbone of event-glue and all events flow through a dispatcher.

It can be easily extended by other classes to give you eventing on those objects.

It has no public accessors, but is exported so you can expand it within your app to add things like a synchronized queue.

Note that dispatchers can feed events into each other, either by passing all events or using a function to filter them (see forward).

*dispatch* (object of type dispatch)

This is the global default event dispatcher. If you use the bind or trigger functions without specifying the :on keyword, *dispatch* is used.

It is created on load via defvar meaning that subsequent loads will preserve the object. It is exported so that in the event you want to extend the dispatch class, you can create your own dispatch object and set it into event-glue:*dispatch* and everything will use your extended class by default.

make-dispatch (function)

(defun make-dispatch ())
  => dispatch

This function creates a new dispatcher.

forward (function)

(defun forward (from to-or-function))
  => nil

Sets up a forward between two dispatchers. from is the dispatcher that we want to forward events from, to-or-function can be either

Note that if A forward to B, triggering an event on A will fire A's handlers before the events are forwarded to B.

Example:

(let* ((all-events (make-dispatch))
       (click-events (make-dispatch))
       (hub (make-dispatch)))
  ;; all-events will get *all* events that hub gets
  (forward hub all-events)
  ;; click-events will only get events where the event name is "click"
  (forward hub
    (lambda (event)
      (when (string= (ev event) "click")
        click-events))))

forwardsp (function)

(defun forwardsp (from to-or-function))
  => to-or-function/nil

Test if from forwards to to-or-function

unforward (function)

(defun unforward (from to-or-function))
  => nil

Undoes a forward created by forward. The to-or-function object must be eq to the one used to set up the forward, or it will not be removed.

Example:

(let ((main (make-dispatch))
      (hub (make-dispatch)))
  (forward hub main)
  (unforward hub main))

event (class)

This class holds information about an event. This consists of the event's name, the event's data (which is an arbitrary object), and any metadata associated with the event. The class is public, allowing you to extend it and add any extra fields required to it (such as a UUID field).

Events are created using the event function, and are generally passed to trigger (or they could be serialized and sent off somewhere).

Events have three public accessors:

ev (accessor)

The event's name, generally a string.

data (accessor)

The event's data. This can be a number, a string, a list...anything you want. There are no restrictions on the data an event can hold.

meta (accessor)

This is a hash-table that consists of information about the event that doesn't necesarily fit into the event's data. For instance, you may want to mark what source an event came from in you app, but that information doesn't pertain to the event's data payload.

event (function)

(defun event (name &key data meta (type 'event)))
  => event

Create a new event object with the given name, data, and meta. name is generally a string, although if you wish you can use symbols or keywords as well. data can be any object you want to attach to the event. meta can be either a hash table or a plist (if plist, key names are string-downcaseed) that gives extra information about the event.

event also takes a :type keyword (which defaults to event) that allows you to create an event of your own type (for instance, you may extend event and use your-event to create event instances).

Example:

(event "click" :data '(:button-id 10) :meta '(:mouse-click t))

;; extension example
(defclass my-event (event) ())
(event "burnourcorruptcapitalistsystemdowntotheground" :type 'my-event)

bind (function)

(defun bind (event-name function &key name (on *dispatch*)))
  => function, unbind-function

Bind function to the given event-name on the dispatch object. This means that whenever trigger is called on dispatch with that event-name, function will be called.

If you pass :* as the event name, you can bind a catch-all event, meaning that your binding is triggered for every event that goes through the dispatcher.

function must take one argument, which will be the event object that was triggered.

The :name keyword allows you to "name" a binding. This is useful when you want to bind an event to anonymous function but you don't want to keep a reference to the function around if you need to unbind (which you'd normally have to do, see unbind). Instead, you can name a binding and then unbind that function with the same name later. The name you pass is converted to a string, so the names :test-event and "test-event" will ultimately resolve to the same name. Be aware of this when naming events.

Note that specifying an event-name/:name pair that already exists will overwrite the existing event binding.

Note that if multiple bindings are attached to the same event, the bindings are fired in the order they were added.

Returns the passed function and also a second function of 0 args that, when called, unbinds the event.

Examples:

;; bind the click-handler function to the "click" event on the global dispatch
(bind "click" 'click-handler)

;; bind to all events
(bind :* (lambda (ev) (format t "got event: ~a~%" ev)))

;; create our own dispatch and bind to the "close" event on it.
(let ((my-dispatch (make-dispatch)))
  (bind "close" (lambda (event) (format t "closed: ~a~%" event)) :on my-dispatch))

;; use named events to unbind an anonymous lambda
(bind "fire" (lambda (ev) (format t "JETSON, ...")) :name "fire:jetson")
;...
(unbind "fire" "fire:jetson")

bind-once (function)

(defun bind-once (event-name function &key name (on *dispatch*)))
  => function, unbind-function

Almost exactly like bind, except that the binding only lasts for one triggering (or until it's removed).

Returns the passed function and also a second function of 0 args that, when called, unbinds the event.

Example:

(bind-once "call" (lambda (ev) (format t "call from ~a~%" (data ev))))
(trigger (event "call" :data "sally"))  ; hi, sally
(trigger (event "call" :data "frank"))  ; frank's call is ignored

unbind (function)

(defun unbind (event-name function-or-name &key (on *dispatch*)))
  => t/nil

Unbind function-or-name from the event-name on the dispatch object. This is essentially the opposite of bind, allowing us to no longer have the given function (or binding name) triggered when the given event-name is triggered.

Returns T if a binding was removed, nil if no changes were made.

Example:

;; bind/unbind using a function
(let ((my-click-fn (lambda (event) (format t "clicked button: ~a~%" (data event)))))
  (bind "click" my-click-fn)
  (unbind "click" my-click-fn))

;; bind/unbind using a named binding
(bind "click" (lamdbda (event) (format t "clicked: ~a~%" (data event))) :name "click:format")
(unbind "click" "click:format")

unbind-all (function)

(defun unbind-all (event-name &key (on *dispatch*)))
  => nil

Unbind all events of type event-name on the dispatcher.

Example:

(bind "click" 'my-click-handler)
(bind "click" 'my-other-click-handler)
(bind "throw" 'ball-was-thrown)
(unbind-all "click")
;; *dispatch* now only contains a handler for "throw"

wipe (function)

(defun wipe (&key preserve-forwards (on *dispatch*)))
  => nil

Wipe out a dispatch object. This includes all handlers of all types.

If :preserve-forwards is true, then the dispatch object will maintain its relationships to other dispatch objects. Otherwise, forwards are removed as well (see forward).

trigger (function)

(defun trigger (event &key (on *dispatch*)))
  => nil

Finally, trigger is what we use to actually fire events.

Examples:

(bind "click" (lambda (event) (format t "clicked: ~a~%" (data event))))
(bind "click" (lambda (event) (format t "click!~%")))
(trigger (event "click" :data 'red-button))

Tests

Load up the event-glue-test system and run (event-glue-test:run-tests).

License

MIT.


Next: , Previous: , Up: Top   [Contents][Index]

2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 event-glue

Author

Andrew Danger Lyon <orthecreedence@gmail.com>

License

MIT

Description

A simple framework for event-based architectures.

Version

0.1.0

Source

event-glue.asd (file)

Components

Next: , Previous: , Up: Top   [Contents][Index]

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Previous: , Up: Files   [Contents][Index]

3.1 Lisp


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.1 event-glue.asd

Location

event-glue.asd

Systems

event-glue (system)


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.2 event-glue/package.lisp

Parent

event-glue (system)

Location

package.lisp

Packages

event-glue


Previous: , Up: Lisp files   [Contents][Index]

3.1.3 event-glue/event.lisp

Dependency

package.lisp (file)

Parent

event-glue (system)

Location

event.lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

4 Packages

Packages are listed by definition order.


Previous: , Up: Packages   [Contents][Index]

4.1 event-glue

Source

package.lisp (file)

Nickname

ev

Use List

common-lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Exported definitions


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.1 Special variables

Special Variable: *dispatch*

Our global dispatch handler. This is the default handler used if a dispatcher is not specified in event operations.

Package

event-glue

Source

event.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.2 Functions

Function: bind EVENT-NAME FUNCTION &key NAME (ON DISPATCH)

Bind a function to an event. Optionally allows naming the binding so it can be removed later on without the reference to the bound function.

Package

event-glue

Source

event.lisp (file)

Function: bind-once EVENT-NAME FUNCTION &key NAME (ON DISPATCH)

Bind a function to an event, but clear the binding out once the event has been triggered once.

Package

event-glue

Source

event.lisp (file)

Function: event NAME &key DATA META TYPE

Easy wrapper for creating a standard event object. Meta is a plist of optional data to set (top-level) into the event object.

Package

event-glue

Source

event.lisp (file)

Function: forward FROM TO-OR-FUNCTION

Forward events from one dispatcher to another. If the second dispatcher is given as a function, that function must return either another dispatcher or nil. This lets you forward specific events at runtime based on data within the event.

Package

event-glue

Source

event.lisp (file)

Function: forwardsp FROM TO-OR-FUNCTION

Determine if the given from -> to forward is active. Returns either to-or-function or nil.

Package

event-glue

Source

event.lisp (file)

Function: make-dispatch &optional TYPE

Make a dispatcher.

Package

event-glue

Source

event.lisp (file)

Function: trigger EVENT &key (ON DISPATCH)

Trigger en event.

Package

event-glue

Source

event.lisp (file)

Function: unbind EVENT-NAME FUNCTION-OR-NAME &key (ON DISPATCH)

Unbind an event/function pair. If function-or-name contains a non-function value, the value is used in a name lookup instead. This allows removing an event/function binding by its name (as specified by :name in the bind function) which can be nice when the original lambda is no longer around.

Package

event-glue

Source

event.lisp (file)

Function: unbind-all EVENT-NAME &key (ON DISPATCH)

Unbind all handlers for the given event name.

Package

event-glue

Source

event.lisp (file)

Function: unforward FROM TO-OR-FUNCTION

Undo a forward created by forward.

Package

event-glue

Source

event.lisp (file)

Function: wipe &key PRESERVE-FORWARDS (ON DISPATCH)

Wipe out all handlers for a dispatch object.

Package

event-glue

Source

event.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.3 Generic functions

Generic Function: data OBJECT
Generic Function: (setf data) NEW-VALUE OBJECT
Package

event-glue

Methods
Method: data (EVENT event)
Method: (setf data) NEW-VALUE (EVENT event)

Arbitrary data attached to the event. Usually a set of args.

Source

event.lisp (file)

Generic Function: ev OBJECT
Generic Function: (setf ev) NEW-VALUE OBJECT
Package

event-glue

Methods
Method: ev (EVENT event)
Method: (setf ev) NEW-VALUE (EVENT event)

Holds the event’s name.

Source

event.lisp (file)

Generic Function: meta OBJECT
Generic Function: (setf meta) NEW-VALUE OBJECT
Package

event-glue

Methods
Method: meta (EVENT event)
Method: (setf meta) NEW-VALUE (EVENT event)

Any top-level meta associated with the event, used to describe it.

Source

event.lisp (file)


Previous: , Up: Exported definitions   [Contents][Index]

5.1.4 Classes

Class: dispatch ()

The dispatch class is what event listeners bind to. Events flow throw it.

Package

event-glue

Source

event.lisp (file)

Direct superclasses

standard-object (class)

Direct methods
Direct slots
Slot: handlers

Holds the dispatcher’s event handlers (event-name -> fn).

Initform

(make-hash-table :test (function equal))

Readers

dispatch-handlers (generic function)

Writers

(setf dispatch-handlers) (generic function)

Slot: handler-names

Holds named event name -> fn bindings for easy lookups.

Initform

(make-hash-table :test (function equal))

Readers

dispatch-handler-names (generic function)

Writers

(setf dispatch-handler-names) (generic function)

Slot: forwards

Holds any other dispatchers this dispatcher forwards to.

Initargs

:forwards

Readers

dispatch-forwards (generic function)

Writers

(setf dispatch-forwards) (generic function)

Class: event ()

Describes an event and any data it holds.

Package

event-glue

Source

event.lisp (file)

Direct superclasses

standard-object (class)

Direct methods
  • print-object (method)
  • meta (method)
  • meta (method)
  • data (method)
  • data (method)
  • ev (method)
  • ev (method)
Direct slots
Slot: ev

Holds the event’s name.

Initargs

:ev

Readers

ev (generic function)

Writers

(setf ev) (generic function)

Slot: data

Arbitrary data attached to the event. Usually a set of args.

Initargs

:data

Readers

data (generic function)

Writers

(setf data) (generic function)

Slot: meta

Any top-level meta associated with the event, used to describe it.

Initargs

:meta

Initform

(make-hash-table :test (function equal))

Readers

meta (generic function)

Writers

(setf meta) (generic function)


Previous: , Up: Definitions   [Contents][Index]

5.2 Internal definitions


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.1 Functions

Function: make-lookup-name EVENT-NAME NAME

Standardizes the naming convention for named event names.

Package

event-glue

Source

event.lisp (file)


Previous: , Up: Internal definitions   [Contents][Index]

5.2.2 Generic functions

Generic Function: dispatch-forwards OBJECT
Generic Function: (setf dispatch-forwards) NEW-VALUE OBJECT
Package

event-glue

Methods
Method: dispatch-forwards (DISPATCH dispatch)
Method: (setf dispatch-forwards) NEW-VALUE (DISPATCH dispatch)

Holds any other dispatchers this dispatcher forwards to.

Source

event.lisp (file)

Generic Function: dispatch-handler-names OBJECT
Generic Function: (setf dispatch-handler-names) NEW-VALUE OBJECT
Package

event-glue

Methods
Method: dispatch-handler-names (DISPATCH dispatch)
Method: (setf dispatch-handler-names) NEW-VALUE (DISPATCH dispatch)

Holds named event name -> fn bindings for easy lookups.

Source

event.lisp (file)

Generic Function: dispatch-handlers OBJECT
Generic Function: (setf dispatch-handlers) NEW-VALUE OBJECT
Package

event-glue

Methods
Method: dispatch-handlers (DISPATCH dispatch)
Method: (setf dispatch-handlers) NEW-VALUE (DISPATCH dispatch)

Holds the dispatcher’s event handlers (event-name -> fn).

Source

event.lisp (file)


Previous: , Up: Top   [Contents][Index]

Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts

Jump to:   E   F   L  
Index Entry  Section

E
event-glue.asd: The event-glue<dot>asd file
event-glue/event.lisp: The event-glue/event<dot>lisp file
event-glue/package.lisp: The event-glue/package<dot>lisp file

F
File, Lisp, event-glue.asd: The event-glue<dot>asd file
File, Lisp, event-glue/event.lisp: The event-glue/event<dot>lisp file
File, Lisp, event-glue/package.lisp: The event-glue/package<dot>lisp file

L
Lisp File, event-glue.asd: The event-glue<dot>asd file
Lisp File, event-glue/event.lisp: The event-glue/event<dot>lisp file
Lisp File, event-glue/package.lisp: The event-glue/package<dot>lisp file

Jump to:   E   F   L  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   (  
B   D   E   F   G   M   T   U   W  
Index Entry  Section

(
(setf data): Exported generic functions
(setf data): Exported generic functions
(setf dispatch-forwards): Internal generic functions
(setf dispatch-forwards): Internal generic functions
(setf dispatch-handler-names): Internal generic functions
(setf dispatch-handler-names): Internal generic functions
(setf dispatch-handlers): Internal generic functions
(setf dispatch-handlers): Internal generic functions
(setf ev): Exported generic functions
(setf ev): Exported generic functions
(setf meta): Exported generic functions
(setf meta): Exported generic functions

B
bind: Exported functions
bind-once: Exported functions

D
data: Exported generic functions
data: Exported generic functions
dispatch-forwards: Internal generic functions
dispatch-forwards: Internal generic functions
dispatch-handler-names: Internal generic functions
dispatch-handler-names: Internal generic functions
dispatch-handlers: Internal generic functions
dispatch-handlers: Internal generic functions

E
ev: Exported generic functions
ev: Exported generic functions
event: Exported functions

F
forward: Exported functions
forwardsp: Exported functions
Function, bind: Exported functions
Function, bind-once: Exported functions
Function, event: Exported functions
Function, forward: Exported functions
Function, forwardsp: Exported functions
Function, make-dispatch: Exported functions
Function, make-lookup-name: Internal functions
Function, trigger: Exported functions
Function, unbind: Exported functions
Function, unbind-all: Exported functions
Function, unforward: Exported functions
Function, wipe: Exported functions

G
Generic Function, (setf data): Exported generic functions
Generic Function, (setf dispatch-forwards): Internal generic functions
Generic Function, (setf dispatch-handler-names): Internal generic functions
Generic Function, (setf dispatch-handlers): Internal generic functions
Generic Function, (setf ev): Exported generic functions
Generic Function, (setf meta): Exported generic functions
Generic Function, data: Exported generic functions
Generic Function, dispatch-forwards: Internal generic functions
Generic Function, dispatch-handler-names: Internal generic functions
Generic Function, dispatch-handlers: Internal generic functions
Generic Function, ev: Exported generic functions
Generic Function, meta: Exported generic functions

M
make-dispatch: Exported functions
make-lookup-name: Internal functions
meta: Exported generic functions
meta: Exported generic functions
Method, (setf data): Exported generic functions
Method, (setf dispatch-forwards): Internal generic functions
Method, (setf dispatch-handler-names): Internal generic functions
Method, (setf dispatch-handlers): Internal generic functions
Method, (setf ev): Exported generic functions
Method, (setf meta): Exported generic functions
Method, data: Exported generic functions
Method, dispatch-forwards: Internal generic functions
Method, dispatch-handler-names: Internal generic functions
Method, dispatch-handlers: Internal generic functions
Method, ev: Exported generic functions
Method, meta: Exported generic functions

T
trigger: Exported functions

U
unbind: Exported functions
unbind-all: Exported functions
unforward: Exported functions

W
wipe: Exported functions

Jump to:   (  
B   D   E   F   G   M   T   U   W  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
D   E   F   H   M   S  
Index Entry  Section

*
*dispatch*: Exported special variables

D
data: Exported classes

E
ev: Exported classes

F
forwards: Exported classes

H
handler-names: Exported classes
handlers: Exported classes

M
meta: Exported classes

S
Slot, data: Exported classes
Slot, ev: Exported classes
Slot, forwards: Exported classes
Slot, handler-names: Exported classes
Slot, handlers: Exported classes
Slot, meta: Exported classes
Special Variable, *dispatch*: Exported special variables

Jump to:   *  
D   E   F   H   M   S  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   C   D   E   P   S  
Index Entry  Section

C
Class, dispatch: Exported classes
Class, event: Exported classes

D
dispatch: Exported classes

E
event: Exported classes
event-glue: The event-glue system
event-glue: The event-glue package

P
Package, event-glue: The event-glue package

S
System, event-glue: The event-glue system

Jump to:   C   D   E   P   S