Go to the first, previous, next, last section, table of contents.

Muq Event System Overview

The Muq event system is a general facility for steering complex computations, with or without explicit user intervention.

It provides the ability to signal and handle hardware and software faults either entirely in software or with the active participation of the user, hence subsumes the role of unix signals and signal handlers and the debugger core, but it should not be thought of primarily as a specialized mechanism for catching errors, but rather as a powerful, general control mechanism for controlling complex programs and building sophisticated user interfaces.

The event system is based on a three-phase model of the problem resolution process:

  1. Describing the problem.
  2. Selecting the best available way of continuing the computation.
  3. Executing the selected continuation.

Here is a typical sequence of events when using the event system. We suppose that part of an application is attempting to access a netserver as part of performing some task for a user:

  1. The application registers several restarts for continuation options such as
  2. The application registers several handlers for problems which might arise during this server-access attempt, such as Some of these handlers may operate entirely invisibly, such as ones that retry or try another server, and some might wish to query the user, such one deciding whether to pay a dollar a byte.
  3. The application initiates the server access attempt.
  4. A problem is detected. A description of the problem is constructed, and the event system activated to resolve it.
  5. The handler registry is searched for handlers claiming to be able to solve this sort of problem, and an appropriate one selected.
  6. The handler searches the restart registry to see what its current options are, consults the problem description, possibly consults the user, and finally invokes a particular restart.
  7. The restart does something expected to resolve the problem, often a goto to some appropriate tag, aborting part of the computation and continuing along a backup path, but perhaps merely (for example) changing some parameters in the network interface.

This problem resolution model leads in a natural way to requirements for the following sets of tools:

The Muq event system provides the following tools to meet these requirements:

Describing problems
The class Event is provided. Each instance of this class represents a particular kind of problem, and inheritance links between these instances describe the relationships between these kinds of problems. Thus, "diskWriteError" may inherit from "diskError" which might inherit from "ioError" which might inherit from "error". This inheritance lattice helps the programmer precisely describe the set of problems which a particular handler understands. The functions signal, warn, error and cerror are provided for explicitly invoking the event system on a particular event. (The server also implicitly invokes these when it encounters problems.)
Registering restarts
The withRestartDo{ ... } construct allows execution of a block of code with a given restart active.
Registering handlers
The withHandlersDo{ ... } construct allows execution of a block of code with a given set of handlers active.
Searching the handler registry
This is done internally by signal and kin, which also server to select and invoke handlers.
Searching the restart registry
The findRestart function may be used to find a single restart. The computeRestarts[ function may be used to return some or all active restarts. The invokeRestart operator allows invocation of any selected restart.

One concrete example is often worth any amount of abstract hand-waving. Here's a simple example which exercises all the basic event system functions. Even without having been formally introduced to all the functions used, the general idea may come though:

makeEvent --> _myEvent

withTag my-tag do{
    [   :function :: 'my-tag goto ;
        :name     'my-restart
    | ]withRestartDo{
        [   _myEvent
            ::  { [] -> [] ! }
                'my-restart invokeRestart
        | ]withHandlerDo{
            [ :event _myEvent | ]signal
    }   }

    t if
        nil --> _looksGood
        t   --> _looksGood

The above example is a fairly complete exercise of the fundamental three layers (tags, restarts, handlers) of the event system:

We now discuss these tools in more detail.

Go to the first, previous, next, last section, table of contents.