gecko-dev/modules/schedulr/public/schedulr.htm
1998-03-28 02:44:41 +00:00

444 lines
25 KiB
HTML

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (WinNT; U) [Netscape]">
<TITLE>System Scheduler Spec</TITLE>
</HEAD>
<BODY>
<H1>
System Scheduler specification</H1>
Last Update: Jan. 12, 1998
<P>The Scheduler is responsible for keeping track of when events such as scheduled
updates are supposed to occur, and to cause those events to occur.&nbsp;
In the interest of reusable components, the scheduler itself doesn't have
any knowledge of the client or of scheduled updates; rather, it will be
implemented as an API level service that will execute a specific callback
when the designated time occurs.&nbsp; The scheduling service will not
have any UI of its own but will rely on its clients to provide user indication
of scheduled events.
<H2>
Functionality</H2>
The scheduling service provides the following functionality:
<UL>
<LI>
Allows clients to register an event to occur at a particular time, optionally
within a range.&nbsp; When the time occurs, the function specified in the
event is called in its own thread, which terminates after the event occurs.&nbsp;
The scheduler can schedule events to occur only once or to repeat at a
given interval.</LI>
<LI>
Allows registration of callbacks to notify observers of events that are
scheduled, executed, or removed from the scheduling queue</LI>
<LI>
Allows all items in the queue to be executed immediately, without regard
to the current time</LI>
<LI>
Allows all items in the queue to be held so they do not execute, regardless
of whether the events' times have elapsed.</LI>
</UL>
The service does not
<UL>
<LI>
Guarantee any level of accuracy; the time specified in the event is the
earliest time at which the event will fire, and events in an time range
will not fire after the specified end time, but otherwise, the scheduler
will make a best-effort attempt to match the given schedule</LI>
<LI>
Persist information across Navigator startup.&nbsp; Items in the queue
when the scheduler is shutdown will be discarded and will not automatically
be reinstated into the queue when Navigator starts up again.</LI>
<LI>
Allow clients to determine the state of their scheduled events, or whether
a specific event has fired.&nbsp; However, a client can register itself
as an observer of event execution, after which it will receive notifications
of every event that was fired.</LI>
</UL>
In order to use the services that the scheduler provides, a scheduler instance
must first be created; subsequent calls to the scheduler can then reference
this instance of the scheduler.&nbsp; The scheduler does not make use of
global variables and therefore is not limited to a single instance, however,
it is expected that there will be only scheduler instance of the scheduler in
the client.
<H2>
APIs - Application Programming Interfaces</H2>
Interfaces for the scheduler fall into three categories.&nbsp; The first
set controls the operation of the scheduler itself, including starting
and stopping the scheduler; the second type of interface allows clients
to add and remove events and observers from the scheduler.&nbsp; The third
type covers the interfaces to the callbacks that the scheduler issues in
order to fire an event or to notify its observers.
<H3>
Scheduler Types and Structures</H3>
<H5>
<U>SchedulerPtr</U></H5>
<TT>typedef void *SchedulerPtr;</TT>
<P>All Scheduler APIs (with the exception of <TT>SchedulerStart</TT>) require
a reference to a scheduler instance in the form of a reference of type
<TT>SchedulerPtr</TT>.&nbsp; A <TT>SchedulerPtr</TT> is returned from <TT>SchedulerStart</TT>,
and its value is used as a handle for a scheduler.&nbsp; The structure
referenced by a <TT>SchedulerPtr</TT> should be considered an opaque entity;
do not directly manipulate any data referenced by a <TT>SchedulerPtr</TT>
reference.
<H5>
<U>SchedulerErr</U></H5>
<TT>typedef enum SchedulerErr {</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_BEGIN = -5,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_BAD_EVENT
= -5,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_BAD_TIME,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_BAD_PARAMETER,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_OUT_OF_MEMORY,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_INVALID_SCHEDULER,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_ERR_NOERR = 0,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_WARN_EVENTS_DROPPED,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SCHED_WARN_END = 1</TT>
<BR><TT>} SchedulerErr;</TT>
<P>Most APIs for the scheduler return a <TT>SchedulerErr</TT> type.&nbsp;
<TT>SchedulerErr</TT> is a typedef for a signed integer value; zero is
defined as no error (successful operation).&nbsp; Negative values are errors
(could not complete operation), and positive values are warnings (operation
completed with comments). All functions (even those which below indicate
that they "cannot fail") can return a <TT>ERR_SCHEDULER_INVALID</TT> if
the passed in scheduler reference is <TT>NULL</TT>.
<H5>
<U>SchedulerTime</U></H5>
<TT>typedef struct&nbsp; _SchedulerTime {</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRUint32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
repeating;</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRInt32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
range;</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRTime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
baseTime;</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRTime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
start;</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRTime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
end;</TT>
<BR><TT>} SchedulerTime;</TT>
<P>In order to instruct the scheduler to execute an event at a particular
time, clients specify a scheduled time expressed in a SchedulerTime structure.&nbsp;
The SchedulerTime structure has values which correspond to the event's
firing time (<TT>baseTime</TT>), and a start and end time from which the
event is valid (<TT>start</TT> and <TT>end</TT>, respectively).&nbsp; Additionally,
SchedulerTime specifies a <TT>range</TT>, which acts as a randomization
value within which the event's scheduled time can "drift," and a <TT>repeating</TT>
interval, both of whch are expressed in seconds.
<P>The exact time at which an event fires is compued as follows.
<P>Each time an event is to fire, a random value (-<TT>range</TT> &lt;
value &lt; <TT>range</TT>) is computed.&nbsp; This value, given as seconds,
is added to the specified<I> </I><TT>baseTime</TT> to derive the time that
the event is to occur.&nbsp; If the computed firing time is before the
<TT>start</TT> or after the <TT>end</TT> times, the firing time is pinned
to the start or end time.
<P>For repeating events, the event's next firing time is computed by adding
the value of <TT>repeating</TT> expressed in seconds, to the event's <TT>baseTime</TT>.&nbsp;
If the new computed time is falls outside the time interval specified by
the <TT>start</TT> and <TT>end</TT> times, the event "expires" and is removed
from the scheduler.&nbsp; Upon removal from the scheduling queue, expired
events If the event has not expired, a random value is selected as above
and added to this time to derive the new firing time.&nbsp; Note that repeating
events are computed based on the pre-randomized times; that is, the time
around which the range is computed will always be an integral number of
<TT>repeating</TT> intervals past the original <TT>baseTime</TT>.
<P>For example, if an event was scheduled with a time of noon, a range
of 300 (5 minutes) and an interval of 3600 (1 hour), the first event would
fire between 11:55 and 12:05 pm.&nbsp; Subseqent events would be fired
between :55 and :05 of every hour.&nbsp; If an <TT>end</TT> time were also
scheduled at 4:02 pm, then the event that was scheduled for 4 pm (noon
plus three iterations of <TT>interval</TT>) may, with randomization, attempt
to be scheduled for 4:04pm.&nbsp; This value would be pinned to 4:02 for
the actual firing time.&nbsp; However, the next time through, the new base
time would be 5 pm, which is beyond the end.&nbsp; In this case, the event
would simply cease to be scheduled and would be removed from the queue.
<P>Because of the way in which range and repetion are computed, it generally
makes sense to have <TT>repeat</TT> >> <TT>range</TT>.&nbsp; That is, the
interval at which events repeat should generally be greater than the amount
of time within which those events are allowed to drift.&nbsp; However,
from a practical standpoint, the implementation prevents scheduled events
from firing out of sequence, so specifying a range which is larger than
an interval is not an error, however, it may resuilt in a number of events
firing near-simultaneously. If an event added to the scheduler was scheduled
for a time in the past, the event will be fired immediately upon being
added to the scheduler.
<H5>
<U>SchedFuncPtr and SchedFuncDataPtr</U></H5>
<TT>typedef void *SchedFuncDataPtr;</TT>
<BR><TT>typedef void (PR_CALLBACK *SchedFuncPtr)(SchedulerPtr pScheduler,
PRUint32 eventID,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
SchedFuncDataPtr pData)</TT>
<P><TT>SchedFuncPtr</TT> is a prototype for the function which is called
when the scheduler fires an event.&nbsp; The function returns nothing and
accepts three parameters, a reference to the scheduler from which the event
was dispatched, the event ID which identifies the event that executed the
function and an arbitrary argument passed in at event creation.&nbsp; The
third argument is opaque to the scheduler and can be used by clients to
transmit or store state information, etc.&nbsp; The function is called
asynchronously in its own thread, which terminates when the function exits.
<H5>
<U>SchedObsPtr and SchedObsDataPtr</U></H5>
<TT>typedef void *SchedObsDataPtr;</TT>
<BR><TT>typedef void (PR_CALLBACK *SchedObsPtr)(SchedulerPtr pScheduler,
PRUint32 observerID,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
SchedObsDataPtr pData, SchedObsType type,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
PRUint32 eventID, const char *eventName,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
SchedFuncDataPtr pEventData);</TT>
<P>Observer callbacks are specified using the prototype given as <TT>SchedObsPtr</TT>.&nbsp;
When an event is added or removed from the scheduler, or when an event
fires, each observer who has registered with that instance of the scheduler
receives a notification message.&nbsp; The function returns nothing and
receives information on the event that triggered the notification (its
id, name, and event data), what kind of operation (add, remove, fire.)
occurred, and the id and data associated with the specific observer.&nbsp;
Both data pointers are opaque to the scheduler.&nbsp; The event data passed
in (<TT>pEventData</TT>) is the actual data pointer for the event, not
a copy, so observers must be aware that changing the information referred
to in <TT>pEventData</TT> may have unexpected results.&nbsp; Additionally,
because there is no type information associated with <TT>pEventData</TT>,
observers must take particular care when making assumptions about the structure
or usage of <TT>pEventData</TT>.
<H3>
Scheduler Operation</H3>
<TT>SchedulerPtr SchedulerStart(void)</TT>
<P>Creates and initializes an instance of the scheduler.&nbsp; <TT>SchedulerStart</TT>
creates a new (local) NSPR thread in which to run the instance of the scheduler
and returns a reference to a newly created scheduler object.&nbsp; This
object is required for all calls to the scheduler API.&nbsp; The newly
created scheduler object is immediately ready to register and dispatch
events.&nbsp; <TT>SchedulerStart</TT> allocates only enough memory for
the scheduler object itself; any supplementary data structures including
the event and observer queues are allocated when they are first referenced
by <TT>EventAdd</TT> or <TT>ObserverAdd</TT>.&nbsp; If the thread can not
be created or memory can not be allocated, <TT>SchedulerStart</TT> returns
<TT>NULL</TT>.&nbsp;&nbsp; In order to properly cleanup, <TT>SchedulerStop()</TT>
should be called when the scheduler is to cease operation.
<P><TT>SchedulerErr SchedulerStop(SchedulerPtr pScheduler);</TT>
<P><TT>SchedulerStop</TT> halts scheduling of the specified scheduler instance,
deletes any memory referenced by the scheduler's event and observer queues,
and frees the instance of the Scheduler.&nbsp; After calling <TT>SchedulerStop</TT>,
the instance of the scheduler referenced by the specified <TT>SchedulerPtr</TT>
is invalid and must not be used.&nbsp; <TT>SchedulerStop</TT> can not fail
and will always return a successful result code.
<P><TT>SchedulerStop</TT> will instruct the scheduler's thread to halt,
but due to thread synchronization issues, the target thread may take some
time to get around to completing.&nbsp; Halting the scheduler does not
have any impact on any threads running as a result of scheduled events;
once the scheduler fires an event, it has no further control over that
event.
<P><TT>SchedulerErr SchedulerPause(SchedulerPtr pScheduler);</TT>
<P><TT>SchedulerPause</TT> causes the scheduler to cease firing events.&nbsp;
Pausing the scheduler does not affect the the addition of new events to
the scheduling queue, nor does it prevent management of the observer list.&nbsp;
While the scheduler is paused, any events scheduled to fire will be held
in the queue until the scheduler's operation is resumed with <TT>SchedulerResume</TT>.&nbsp;
Calling <TT>SchedulerPause</TT> multiple times will have no effect beyond
the first; <TT>SchedulerPause</TT> can not fail and will always return
a successful result code.
<P><TT>SchedulerErr SchedulerResume(SchedulerPtr pScheduler);</TT>
<P><TT>SchedulerResume</TT> reverses the effect of a previous <TT>SchedulerPause</TT>
call.&nbsp; Events that did not fire while the scheduler queue was paused
will immediately fire, unless their scheduled end time (expiration) has
passed, in which case those items are removed from the queue.&nbsp; Items
removed from the queue in this way cause an event deletion notification
to be sent to the scheduler's observers.&nbsp; All other conditions, including
sending <TT>SchedulerResume</TT> to a scheduler which has not been paused
will always return a successful result code.
<P>Pausing and resuming the scheduler is not reference counted; if multiple
threads have paused the scheduler, the first to resume it will cause the
scheduler to start actively processing events.
<P><TT>SchedulerErr SchedulerFreeze(SchedulerPtr pScheduler);</TT>
<P><TT>SchedulerFreeze</TT> causes the scheduler to both stop processing
events and to reject the addition of new items to the queue.&nbsp; This
function is typically only called internally, since clients do not have
any way to unfreeze the scheduler.&nbsp; The scheduler calls this routine
while it is executing the <TT>FireAll</TT> function in order to make sure
that the scheduling queue stays in a consistent state while it is processing
all of the events.
<P><TT>SchedulerFreeze</TT> will not fail and will always return a successful
result code.
<P><TT>SchedulerErr SchedulerFireAll(SchedulerPtr)</TT>&nbsp;&nbsp;&nbsp;
<B><I>This function is not yet implemented</I></B>
<P><TT>SchedulerFireAll</TT> instructs the scheduler to close the queue
to new requests and sequentially fire all events in the current event queue
without regard to their scheduled time.&nbsp; Notification events will
be sent to observers for each fired event.
<P>In order to prevent new events from being added to the queue as all
existing events are being fired, and therefore creating a potential infinite
loop, the <TT>SchedulerFireAll</TT> function freezes the existing event
queue prior to beginning operation.&nbsp; It will then create a new, empty
event queue for the given scheduler instance.&nbsp; The event queue is
ready to receive new events, but it is paused, preventing execution of
any events from ocurring while the <TT>FireAll</TT> request is processed.&nbsp;
The scheduler then fires each event in the previous queue in sequence;
when it has fired the last event, it will destroy the old event queue and
resume the new one it has created.&nbsp; Normal operation of the scheduler
can then continue.
<P>(insert diagram here)
<H3>
Event and Observer List management</H3>
<TT>SchedulerErr SchedulerAddEvent(SchedulerPtr pScheduler, PRUint32 *pEventID,
const char *szName,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
SchedulerTime *pTime, SchedFuncPtr function, SchedFuncDataPtr pData);</TT>
<P><TT>SchedulerAddEvent</TT> adds an event to the scheduler's event queue.&nbsp;
An event is defined as the combination of a function and its data, scheduled
to fire at a particular time (or set of times).&nbsp; Accordingly, a client
which wishes to add an event needs to specify a time at which the event
should fire, a function to call when the time occurs, and any amount of
data which will be passed to the specified function at the time that the
event is fired.&nbsp; A client may also supply a user-visible name with
which to&nbsp;&nbsp;&nbsp;&nbsp; identify the event.&nbsp; Note that this
name is not used by the scheduler at all and may be <TT>NULL</TT> if no
user-visible name is desired.&nbsp; Both the time and name are copied into
the scheduler's internal structures, so the memory referenced by these
events may be released after making this call.
<P>If successful, SchedulerAddEvent adds the event to the event queue,
assigns a unique <TT>eventID</TT> which can be used to later refer to this
specific event, and returns a successful result code.&nbsp; If <TT>NULL</TT>
is passed in as the reference to the <TT>eventID</TT>, an event ID is still
generated, but the client will be unable to change or delete the event
in the future.&nbsp; Note that <TT>eventID</TT>s are unique only to a particular
scheduler instance; they are not guaranteed to be globally unique across
scheduler instances.
<P><TT>SchedulerAddEvent</TT> can fail for a number of reasons.&nbsp; The
most common is lack of memory.&nbsp; If the event queue needs to be created
or expanded in size to accomodate the new event, the scheduler will fail,
returning <TT>SCHED_ERR_OUT_OF_MEMORY</TT>, and will return 0 as the <TT>eventID</TT>.&nbsp;
Event addition will also fail if the time specified is invalid, is outside
the bounds specified by the event's <TT>start</TT> and <TT>end</TT> times,
or if the given range is negative (<TT>SCHED_ERR_BAD_TIME</TT>); or if
a <TT>NULL</TT> value is given for the function (<TT>SCHED_ERR_BAD_PARAMETER</TT>).
<P>Upon successful addition of the event, the scheduler will send notification
messages to its observers indicating that an event was added to the queue.&nbsp;
Included in the notification will be a reference to the scheduler and the
<TT>eventID</TT>, from which the observers can determine additional information
about the event.&nbsp; Because notification messages are synchronous, the
observers should not perform any lengthy operation when notified, as that
will impact the performance of event addition.&nbsp; Internally, the scheduler
adds the new event into its event queue, sorted by when the event is scheduled
to fire.
<P><TT>SchedulerErr SchedulerRemoveEvent(SchedulerPtr pScheduler, PRUint32
eventID);</TT>
<P><TT>SchedulerRemoveEvent</TT> removes a previously added event from
the scheduler's event queue.&nbsp; The event to remove is specified by
its <TT>eventID</TT>, previously assigned by <TT>SchedulerAddEvent</TT>.&nbsp;
If the specified event ID is invalid, the scheduler will return an error,
<TT>SCHED_ERR_BAD_EVENT</TT>, and no operation will be performed.
<P>Upon successful removal of an event, the scheduler will send notification
messages to its observers indicating that an event was removed.&nbsp; Including
in the notification will be the <TT>eventID</TT>, from which the observers
can determine additional information about the event.&nbsp; Because notification
messages are synchronous, the observers should not perform any lengthy
operation when notified, as that will impact the performance of event removal.&nbsp;
After all observers have been notified, the memory associated with the
event will be destroyed and the <TT>eventID</TT> will no longer be valid.
<P><TT>SchedulerErr SchedulerFindEvent(SchedulerPtr, uint eventID, &amp;time,
&amp;name, &amp;function, &amp;data</TT>)
<BR>&nbsp;&nbsp; <B><I>This function is not yet implemented</I></B>
<P><TT>SchedulerErr SchedulerAddObserver(SchedulerPtr pScheduler, PRUint32
*pObserverID, SchedObsType type,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
SchedObsPtr function, SchedObsDataPtr pData);</TT>
<P><TT>SchedulerAddObserver</TT> adds an observer to the specified scheduler's
observer list.&nbsp; An observer is a function which is called when the
scheduler adds, removes, or fires an event.&nbsp; Which of these actions
trigger a notification for a given observer is specified in the observer's
type, which is a bitfield made up of the union of the following values:
<P><TT>#define SCHED_OBSERVE_ADD&nbsp;&nbsp;&nbsp; 1</TT>
<BR><TT>#define SCHED_OBSERVE_FIRE&nbsp;&nbsp; 2</TT>
<BR><TT>#define SCHED_OBSERVE_REMOVE 4</TT>
<P>When an observer is notified that something has happened, the observer's
function is called with the id and name of the event that fired, along
with the event's data pointer and the observer's id and the data pointer
specified in the AddObserver call.&nbsp; Note that the event data that
is passed in is not a copy of the event's data, but a pointer to it, so
altering the data will cause the data to be altered for the next iteration
of the event, as well as for subsequent observers which are notified.&nbsp;
However, since observers will receive notification for all events on an
event queue, observers must take care that they actually know the datatype
of the information passed in the event's data fields.&nbsp; In no case
should the event data be freed.
<P>Observer lists are not terribly efficient; the mechanism used to determine
which observers receive a given notification is done by linearly searching
the list of observers, so for performance reasons, callers should not specify
a large number of observers for any given scheduler instance.&nbsp; Indeed,
the scheduler was designed with only one specific observer in mind -- the
code which handles the display of status information within the client
user interface.
<P>Like the corresponding <TT>AddEvent</TT> function, above, adding an
observer causes the scheduler to generate a unique <TT>observerID</TT>,
which can later be used to remove the observer.&nbsp; Also like <TT>AddEvent</TT>,
the <TT>observerID</TT> is unique only within a scheduler instance.&nbsp;
<TT>ObserverIDs</TT> and <TT>EventID</TT>s are not interchangeable; their
namespace may overlap.&nbsp; Therefore, it's important that the caller
keep track of which identifiers represent events and which represent observers.
If NULL is passed in for the observerID, an observer ID is generated, but
it is not returned to the caller.
<P><TT>SchedulerAddObserver</TT> can fail if memory can not be allocated
to store the observer or create the observer queue, or if the function
specified is <TT>NULL</TT>.&nbsp; In each failure case, the <TT>observerID</TT>
returned is undefined.
<P><TT>SchedulerErr SchedulerRemoveObserver(SchedulerPtr pScheduler, PRUint32
observerID)</TT>
<P><TT>SchedulerRemoveObserver</TT> removes an observer from the scheduer's
observer list.&nbsp; That observer no longer receives notification messages
and the scheduler frees any memory it has allocated to track the specified
observer.&nbsp; If no observer with the given ID exists, the function returns
<TT>SCHED_ERR_BAD_PARAMETER</TT>, and no operation is performed.
<BR>&nbsp;
</BODY>
</HTML>