NSPR Reference: Chapter 7 Monitors
Description: The Sun-Netscape Alliance, a strategic alliance formed by America Online and Sun Microsystems, Inc., is delivering iPlanet e-commerce software and enterprise solutions that enable companies to compete successfully in the Net Economy
Keywords: electronic commerce, ecommerce, ebusiness, e-business, e-commerce, enterprise software, net economy, Netscape, Sun Microsystems, Sun-Netscape Alliance, iPlanet, internet software

NSPR Reference Previous Contents Next

## Chapter 7 Monitors

In addition to the mutex type `PRLock`, NSPR provides a special type, `PRMonitor`, for use in Java programming. This chapter describes the NSPR API for creation and manipulation of a mutex of type `PRMonitor`.

Monitor Type
Monitor Functions

With a mutex of type `PRLock`, a single thread may enter the monitor only once before it exits, and the mutex can have multiple associated condition variables.

With a mutex of type `PRMonitor`, a single thread may re-enter a monitor as many times as it sees fit. The first time the thread enters a monitor, it acquires the monitor's lock and the thread's entry count is incremented to 1. Each subsequent time the thread successfully enters the same monitor, the thread's entry count is incremented again, and each time the thread exits the monitor, the thread's entry count is decremented. When the entry count for a thread reaches zero, the thread releases the monitor's lock, and other threads that were blocked while trying to enter the monitor will be rescheduled.

A call to `PR_Wait` temporarily returns the entry count to zero. When the calling thread resumes, it has the same entry count it had before the wait operation.

Unlike a mutex of type `PRLock`, a mutex of type `PRMonitor` has a single, implicitly associated condition variable that may be used to facilitate synchronization of threads with the change in state of monitored data.

For an introduction to NSPR thread synchronization, including locks and condition variables, see Chapter 1 "Introduction to NSPR"

## Monitor Type

With the exception of `PR_NewMonitor`, which creates a new monitor object, all monitor functions require a pointer to an opaque object of type `PRMonitor`.

#### PRMonitor

A `PRMonitor` object is an opaque structure managed entirely by the client. Clients create them when needed and must destroy them when no longer needed.

##### Syntax

    #include <prmon.h>

    typedef struct PRMonitor PRMonitor;

## Monitor Functions

All monitor functions are thread-safe. However, this safety does not extend to protecting the monitor object from deletion.

`PR_NewMonitor` creates a new monitor.

- `PR_DestroyMonitor` destroys a monitor object.

- `PR_EnterMonitor` enters the lock associated with a specified monitor.

- `PR_ExitMonitor` decrements the entry count associated with a specified monitor.

- `PR_Wait` waits for a notify on a specified monitor's condition variable.

- `PR_Notify` notifies a thread waiting on a specified monitor's condition variable.

- `PR_NotifyAll` notifies all threads waiting on a specified monitor's condition variable.

#### PR_NewMonitor

Creates a new monitor object. The caller is responsible for the object and is expected to destroy it when appropriate.

##### Syntax

    #include <prmon.h>

    PRMonitor* PR_NewMonitor(void);

##### Returns

The function returns one of the following values:

If successful, a pointer to a `PRMonitor` object. This pointer is required for all subsequent monitor function calls.

- If unsuccessful (for example, if some operating system resource is unavailable), `NULL`.

##### Description

A newly created monitor has an entry count of zero.

#### PR_DestroyMonitor

Destroys a monitor object.

##### Syntax

    #include <prmon.h>

    void PR_DestroyMonitor(PRMonitor *mon);

##### Parameter

The function has the following parameter:

    mon
| A reference to an existing structure of type `PRMonitor`.

##### Description

The caller is responsible for guaranteeing that the monitor is no longer in use before calling `PR_DestroyMonitor`. There must be no thread (including the calling thread) in the monitor or waiting on the monitor.

#### PR_EnterMonitor

Enters the lock associated with a specified monitor.

##### Syntax

    #include <prmon.h>

    void PR_EnterMonitor(PRMonitor *mon);

##### Parameter

The function has the following parameter:

    mon
| A reference to an existing structure of type `PRMonitor`.

##### Description

When the calling thread returns, it will have acquired the monitor's lock. Attempts to acquire the lock for a monitor that is held by some other thread will result in the caller blocking. The operation is neither timed nor interruptible.

If the monitor's entry count is greater than zero and the calling thread is recognized as the holder of the lock, `PR_EnterMonitor` increments the entry count by one and returns. If the entry count is greater than zero and the calling thread is not recognized as the holder of the lock, the thread is blocked until the entry count reaches zero. When the entry count reaches zero (or if it is already zero), the entry count is incremented by one and the calling thread is recorded as the lock's holder.

#### PR_ExitMonitor

Decrements the entry count associated with a specified monitor and, if the entry count reaches zero, releases the monitor's lock.

##### Syntax

    #include <prmon.h>

    PRStatus PR_ExitMonitor(PRMonitor *mon);

##### Parameter

The function has the following parameter:

    mon
| A reference to an existing structure of type `PRMonitor`. The monitor object referenced must be one for which the calling thread currently holds the lock.

##### Returns

The function returns one of the following values:

If successful, `PR_Success`.

- If unsuccessful (the calling thread has not entered the monitor), `PR_FAILURE`.

##### Description

If the decremented entry count is zero, `PR_ExitMonitor` releases the monitor's lock. Threads that were blocked trying to enter the monitor will be rescheduled.

#### PR_Wait

Waits for an application-defined state of the monitored data to exist.

##### Syntax

    #include <prmon.h>

    PRStatus PR_Wait(
       PRMonitor *mon,
       PRIntervalTime ticks);

##### Parameters

The function has the following parameters:

    mon
| A reference to an existing structure of type `PRMonitor`.
    ticks
| The amount of time (in `PRIntervalTime` units) that the thread is willing to wait for an explicit notification before being rescheduled.

##### Returns

The function returns one of the following values:

`PR_SUCCESS` means the thread is being resumed from the `PR_Wait` call either because it was explicitly notified or because the time specified by the parameter `ticks` has expired.

- `PR_FAILURE` means `PR_Wait` encountered a system error (such as an invalid monitor reference) or the thread was interrupted by another thread.

##### Description

A call to `PR_Wait` causes the thread to release the monitor's lock, just as if it had called `PR_ExitMonitor` as many times as it had called `PR_EnterMonitor`. This has the effect of making the monitor available to other threads. When the wait is over, the thread regains control of the monitor's lock with the same entry count it had before the wait began.

A thread waiting on the monitor resumes when the monitor is notified or when the timeout specified by the `ticks` parameter elapses. The resumption from the wait is merely a hint that a change of state has occurred. It is the responsibility of the programmer to evaluate the data and act accordingly. This is usually done by evaluating a Boolean expression involving the monitored data. While the Boolean expression is false, the thread should wait. The thread should act on the data only when the expression is true. The boolean expression must be evaluated while in the monitor and within a loop.

In pseudo-code, the sequence is as follows:

    PR_EnterMonitor(&ml);
    while (!expression) wait;
    ... act on the state change ...
    PR_ExitMonitor(&ml);

A thread can be resumed from a wait for a variety of reasons. The most obvious is that it was notified by another thread. If the value of timeout is not `PR_INTERVAL_NO_TIMEOUT`, `PR_Wait` resumes execution after the specified interval has expired. If a timeout value is used, the Boolean expression must include elapsed time as part of the monitored data.

Resuming from the wait is merely an opportunity to evaluate the expression, not an assertion that the expression is true.

#### PR_Notify

Notifies a monitor that a change in state of the monitored data has occurred.

##### Syntax

    #include <prmon.h>

    PRStatus PR_Notify(PRMonitor *mon);

##### Parameter

The function has the following parameter:

    mon
| A reference to an existing structure of type `PRMonitor`.

##### Returns

The function returns one of the following values:

If successful, `PR_SUCCESS`.

- If unsuccessful, `PR_FAILURE`.

##### Description

Notification of a monitor signals the change of state of some monitored data. The changing of that data and the notification must all be performed while in the monitor. When the notification occurs, the runtime promotes a thread that is waiting on the monitor to a ready state. If more than one thread is waiting, the selection of which thread gets promoted cannot be determined in advance. This implies that all threads waiting on a single monitor must have the same semantics. If no thread is waiting on the monitor, the notify operation is a no-op.

#### PR_NotifyAll

Promotes all threads waiting on a specified monitor to a ready state.

##### Syntax

    #include <prmon.h>

    PRStatus PR_NotifyAll(PRMonitor *mon);

##### Parameter

The function has the following parameters:

    mon
| A reference to an existing structure of type `PRMonitor`.

##### Returns

The function returns one of the following values:

If successful, `PR_SUCCESS`.

- If unsuccessful, `PR_FAILURE`.

##### Description

A call to `PR_NotifyAll` causes all of the threads waiting on the monitor to be scheduled to be promoted to a ready state. If no threads are waiting, the operation is no-op.

`PR_NotifyAll` should be used with some care. The expense of scheduling multiple threads increases dramatically as the number of threads increases.

Previous Contents Next

Last Updated May 18, 2001