This section goes over basic events in cl-async and how to use them for various purposes, such as triggering a function after a specific amount of time, or watching an OS file descriptor for changes.


The event class wraps around a libuv event C object. It is accepted by free-event, remove-event, and add-event.


Allows you to access the underlying C object associated with this event.

It’s exported in case you need to do something cl-async doesn’t provide.


Returns t if an event is already freed (via free-event), and nil if it has not been freed. Trying to operate on an event that has been freed will result in an event-freed error.


(defun free-event (event))
  => nil

Frees an event’s underlying event object, and performs any needed cleanup. It is absolutely safe to free an event that is pending (watched by the event loop) or active. Doing so makes the event inactive/non-pending before freeing.


(defun remove-event (event))
  => t/nil

This removes an event from the event loop. The event still exists, and can be added back into the event loop via add-event, but must be activated again after adding back into the loop (by either specifying :active t or giving a timeout in seconds via :timeout.

Returns t on success, nil otherwise (a nil can mean that the event is already removed and doesn’t need to be remove again).


(defun add-event (event &key timeout activate)
  => nil

Makes an event pending (adds it to the event loop it was created with). This is mainly done to resume an event that was removed from the event loop using remove-event.

If :timeout is specified, the event will fire in the given number of seconds regardless of whether or not the other conditions the event is watching for are met.

If :activate is true and :timeout is null, the event t is instead manually activated.

Note that if you omit both :activate and :timeout, the event will be added to the loop but not activated (and will never be run unless you call add-event again with either :activate or :timeout specified).


(defun delay (callback &key time event-cb))
  => event

Run a function asynchronously. Takes two optional parameters: time, the number of seconds to wait before running the given function (run with no delay if nil), and event-cb which can be used to catch application errors should they occur while running callback.

;; example:
(delay (lambda () (format t "Run me immediately after control is given to the event loop.~%")))
(delay (lambda () (format t "I will run 3.2 seconds after calling (delay).~%")) :time 3.2)


(defmacro with-delay ((seconds) &body body))
  => event

Syntax wrapper around delay to make it a bit less annoying to type.

;; example:
(with-delay (5)
  (format t "Five seconds passed!~%"))


(defun interval (callback &key time event-cb))
  => cancel-closure

Like delay, but runs the given callback every time seconds until stopped by either funcalling the returned closure, or calling remove-inteval on the returned closure.


(defmacro with-interval ((seconds) &body body))
  => cancel-closure

Syntax wrapper around interval. Returns the same cancellation closure that interval does.


(defun remove-interval (interval-closure))
  => nil

When given the closure returned from calling interval, stops the timer on the interval (cancels it).


(defun make-event (callback &key event-cb))
  => event

Makes it easy to add an arbitrary event to the event loop. This event needs to either be activated via (add-event event :activate t) (see add-event) or removed manually.

This is a very thin wrapper around delay, in fact all it does is call delay with a one-year delay.


extends event-error

This error is thrown when an event that has been freed is operated on in some way. You can test if an event is freed already using the event-freed-p method.


(defmethod ref ((handle event)))
  => nil

References the event, making it so that the event loop will not exit until the event is freed.

See unref as well.


(defmethod unref ((handle event)))
  => nil

Unreferences the event. This means that even if it’s active in the event loop, the loop can exit without the event being closed/freed.

See ref as well.