%
% x-kernel v3.3
%
% Copyright (c) 1996,1993,1991,1990  Arizona Board of Regents
%

\section{Event Library}\label{event_lib}

The event library provides a mechanism for scheduling a procedure to
be called after a certain amount of time.  By registering a procedure
with the event library, protocols are able to ``timeout'' and act on
messages that have not been acknowledged or to perform periodic
maintenance functions.

\subsection{Type Definitions}\label{event_type_def}

The only event-related type that protocol programmers need be aware of
is the type {\var Event}.  This type is defined by the underlying
platform and is opaque to the protocol programmer.

\subsection{Event Operations}\label{event_ops}

\subsubsection{evSchedule}\label{evSchedule}
\index{evSchedule}

Schedules an event that executes function {\var func} with argument
{\var arg} after delay {\var usec} microseconds; {\var usec} may equal
0.  A handle to the event is returned, and this can be used to cancel
the event at some later time.  When an event fires, a new thread is
created to run function {\var func}.  Note that even after an event
fires and a thread has been scheduled to handle it, the thread does
not run until sometime after the currently executing thread gives up
the processor.  See Section~\ref{thread_lib} for a description of how
threads are scheduled.
\medskip

{\var Event evSchedule(EvFunc func, void *arg, unsigned usec)}

{\var typedef void (*EvFunc)(Event event, void *arg)}
\medskip

Function {\var func} must be of type {\var void} and take two
arguments: the first, of type {\var Event}, is a handle to the event
itself, and the second, of type {\var void *}, is the argument passed
to evSchedule.  In order to satisfy the C compiler type checking rules
when accessing the arguments, function {\var func} must begin by
casting its second argument to be a non-void type.

\subsubsection{evDetach}\label{evDetach}
\index{evDetach}

Releases a handle to an event.  As soon as {\var func} completes, the
internal resources associated with the event are freed.  All events
should eventually be either detached or canceled to assure that system
resources are released.
\medskip

{\var void evDetach(Event event)}
\medskip

\subsubsection{evCancel}\label{evCancel}
\index{evCancel}

Cancels {\var event} and returns {\var EVENT\_FINISHED} if the event
has already happened, {\var EVENT\_RUNNING} if the event is currently
running, and {\var EVENT\_CANCELLED} if the event has not run and can
be guaranteed to not run.  In the case where {\var evCancel} returns
{\var EVENT\_RUNNING}, the caller must be careful to not delete
resources required by the event.
\medskip

{\var EvCancelReturn evCancel(Event event)}

\subsubsection{evIsCancelled}\label{evIsCancelled}
\index{evIsCancelled}

Returns true if an {\var evCancel} has been performed on the event.
Because event handlers receive their event as the first calling
argument, it is possible for a handler to check for cancellation of
itself from other threads.
\medskip

{\var bool evIsCancelled(Event event)}

\subsubsection{evDump}\label{evDump}
\index{evDump}

Displays a {\var ps}-style listing of {\xk} threads when the {\xk} is
compiled with DEBUG mode.  The address of the entry function, the
thread state (pending, scheduled, running, finished, or blocked), the
time relevant to the thread state, and flags (detached or cancelled),
are displayed for each thread controlled by {\xk} monitor.  The
meaning of the time entry varies according to the state.  For pending
threads, the time is the time until it will be scheduled; for other
states it is the time the thread has spent in that state.  The time is
reset on each transition, i.e., it is not cumulative.
\medskip

{\var void evDump(void)}

\subsection{Usage Rules}\label{event_usage}

\subsubsection{Repeating Events}\label{repeat_events}

Each event that is scheduled executes at most one time.  Repeating
events are programmed as illustrated in Figure~\ref{fig:repeat}.

\begin{figure}
\caption{Repeating events \label{fig:repeat}}
\begin{verbatim}

        foo_init()
        {
            ...
            evDetach(evSchedule(func, arg, INTERVAL));
        }

        func(Event self, void *arg)
        {
            actual work
            ...
            evDetach(evSchedule(func, arg, INTERVAL));
        }
\end{verbatim}
\end{figure}

\subsubsection{Cancellable Events}\label{cancel_events}

The {\var evIsCancelled} routine is designed to make it easy to write
events which might be cancelled before (or while) they run.  It is
common practice, for example, for a session to pass session state to a
timeout event.  The {\var evIsCancelled} notification can be used to
synchronize the timeout event and the possible destruction of the
session state.  An example is given in Figure~\ref{fig:cancel}.

\begin{figure}
\caption{Cancellable events \label{fig:cancel}}
\begin{verbatim}

        foo_destroy()
        {
            ...
            evCancel(state->timeoutEvent);
            ...
        }

        foo_timeout(Event self, void *arg)
        {
	    PState *state = (PState *)arg;

            ...
            xPush(lls, retransmitMsg);
            /* xPush may have blocked - check to see if state is still valid */
            if (evIsCancelled(self))
                return;
            state->timeoutEvent = evSchedule(foo_timeout, arg, INTERVAL);
        }
\end{verbatim}
\end{figure}

\subsubsection{Event Granularity}\label{event_gran}

Although the event library uses an efficient representation (timing
wheels) protocol programmers should be careful to not schedule events
that are too fine grained.  For example, in TCP, it is better to
schedule one event for every session rather than for every message
that is sent.
