NSPR Reference: Chapter 24 Multiwait Receive
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 24 Multiwait Receive

This chapter describes the multiwait helper API. Multiwait allows its clients to service an arbitrary number of network file descriptors with a relatively small number of threads.

Multiwait trades off the simplicity of fully synchronous I/O for a limited amount of asynchronous behavior. Its premise is that the connections are mostly idle, spending most of their time waiting for network input. This premise is based on the anticipated behavior of the passive partner (the server) in a client/server relationship. In that environment, the server receives a request from the network, processes that request, sends back the response, and then waits for the next request to arrive. This scenario repeats itself for the lifetime of the connection. If the time of waiting for a request is an order of magnitude or more greater than the time spent in formulating and delivering the response, then multiwait should be applicable.

An incoming request is serviced by a thread from a pool of threads supplied by the client. All threads are assumed to be equivalent and the runtime selects the one most convenient from those available. The client can define different wait groups, that allow separate pools of threads to be associated with different collections of file descriptors.

Multiwait Types
Multiwait Client Functions

## Multiwait Types

The multiwait receive interface defines and uses these types:

`PRRecvWait``
` `PRWaitGroup``
` `PRMWStatus``
` `PRMemoryDescriptor```

#### PRRecvWait

Represents a receive wait object.

##### Syntax

    #include <prmwait.h>

    typedef struct PRRecvWait
    {
       PRCList internal;
       PRFileDesc *fd;
       PRMWStatus outcome;
       PRIntervalTime timeout;
       PRInt32 bytesRecv;
       PRMemoryDescriptor buffer;
       PRMWaitClientData *client;
    } PRRecvWait;

##### Description

A receive wait object contains the file descriptor that is subject to the wait and the amount of time the channel should block before abandoning the process. (The beginning epoch is established when the object is presented to the runtime.)

The completion status of the wait operation is noted in the object's `outcome` field. The fields are not valid when the NSPR runtime is in possession of the object.

The memory descriptor describes an interval of writable memory in the caller's address space where data from an initial read can be placed. The description can indicate a null interval.

internal | This field is for internal runtime linkages. Clients should not attempt to modify anything in this area.
`fd` | A pointer to a valid file descriptor that is associated with this object. This is the network file descriptor that is expected to become ready for receive.
`outcome` | The `outcome` field constrains the status of the object. It is set by the runtime to `PR_MW_PENDING` when the object is first accepted. As long as the value remains `PR_MW_PENDING`, none of the other fields are assumed valid.
`bytesRecv` | When the operation is complete, this field contains the number of bytes transferred from the network to the client's buffer,`buffer`. Any number of bytes from zero to the length of the buffer can be indicated.
`buffer` | A description of the memory reserved by the client in which to store data arriving from the network. This descriptor can indicate a null (zero-length) buffer, which implies that the file descriptor is receive ready only.
`client` | A pointer to arbitrary client data associated with this wait operation. The client defines the data type `PRMWaitClientData`. This field is ignored by the runtime.

#### PRWaitGroup

Represents a wait group.

##### Syntax

    #include <prmwait.h>

    typedef struct PRWaitGroup PRWaitGroup;

##### Description

The client can define several wait groups in order to semantically tie a collection of file descriptors for a single purpose. This allows easier dispatching of threads that returned with active file descriptors from the wait function.

The `PRWaitGroup` structure is opaque. The runtime deals with its creation, destruction, and internal structure. Most of the API's methods require a pointer to a wait group (also known as the wait group's identity) as an argument. There is a default wait group, represented by a `NULL` identity.

#### PRMWStatus

Represents the completion status of a receive wait object.

##### Syntax

    #include <prmwait.h>

    typedef enum PRMWStatus
    {
        PR_MW_PENDING = 1,
        PR_MW_SUCCESS = 0,
        PR_MW_FAILURE = -1,
        PR_MW_TIMEOUT = -2,
        PR_MW_INTERRUPT = -3
    } PRMWStatus;

##### Description

The `PRMWStatus` enumeration is used to indicate the completion status of a receive wait object. Generally stated, a positive value indicates that the operation is not yet complete. A zero value indicates success (similar to `PR_SUCCESS`) and any negative value is an indication of failure. The reason for the failure can be retrieved by calling `PR_GetError`.

`PR_MW_PENDING` | The operation is still pending. None of the other fields of the object is currently valid.
`PR_MW_SUCCESS` | The operation is complete and it was successful.
`PR_MW_FAILURE` | The operation failed. The reason for the failure can be retrieved by calling `PR_GetError`.
`PR_MW_TIMEOUT` | The amount of time allowed for by the object's `timeout` field has expired without the operation otherwise coming to closure.
`PR_MW_INTERRUPT` | The operation was canceled by the client, either by calling `PR_CancelWaitFileDesc` or by canceling the entire wait group using `PR_CancelWaitGroup`.

#### PRMemoryDescriptor

Represents an interval of memory.

##### Syntax

    #include <prmwait.h>

    typedef struct PRMemoryDescriptor
    {
        void *start;
        PRSize length;
    } PRMemoryDescriptor;

##### Description

A descriptor for an interval of memory.

`start` | This is the address of the first byte of memory that the descriptor defines.
`length` | The length of the memory in bytes.

## Multiwait Client Functions

Multiwait functions that create and operate on wait groups and wait receive objects are:

`PR_CreateWaitGroup``
` `PR_DestroyWaitGroup``
` `PR_AddWaitFileDesc``
` `PR_WaitRecvReady``
` `PR_CancelWaitFileDesc``
` `PR_CancelWaitGroup```

#### PR_CreateWaitGroup

Creates a wait group.

##### Syntax

    #include <prmwait.h>

    PRWaitGroup* PR_CreateWaitGroup (PRInt32 size_hint);

##### Parameters

The function has this parameter:

`size_hint` | A hint as to the size of the hash table used to manage the set of descriptors. This number may be applied to the initial size of the table, but does not limit the number of entries that the wait group can handle.

##### Returns

If successful, returns a reference to an object that was allocated by and owned by the runtime. The reference becomes the wait group identifier. The reference remains valid until it is explicitly destroyed by calling `PR_DestroyWaitGroup`.

If unsuccessful, returns `NULL`. Retrieve the reason for the failure using `PR_GetError`. The only reason for failure is a heap allocation failure (`PR_OUT_OF_MEMORY_ERROR`).

##### Description

This function creates a new wait group, using the specified size hint. A wait group allows a client to partition the set of file descriptors according to some arbitrary rules. Each wait group is unique, including the default wait group, specified by a `NULL` identifier. A wait request that was added under a wait group is serviced by a call to `PR_WaitRecvReady` that specifies the same wait group.

#### PR_DestroyWaitGroup

Destroys a wait group.

##### Syntax

    #include <prmwait.h>

    PRStatus PR_DestroyWaitGroup (PRWaitGroup *group);

##### Parameters

The function has this parameter:

`group` | The identity of the wait group to cancel. This must refer to a valid wait group and the group must not have any waiting threads or wait descriptors.

##### Returns

If the wait group can be successfully destroyed, returns `PR_SUCCESS`. Otherwise, returns `PR_FAILURE`. Retrieve the reason for the failure by calling `PR_GetError`.

##### Description

This function frees the memory allocated by `PR_CreateWaitGroup`. The wait group must not contain any receive wait objects. Clear the wait group of all receive wait objects using the `PR_CancelWaitGroup`, before calling this function.

Error codes that can be returned by `PR_GetError` when this function fails are:

`PR_INVALID_ARGUMENT_ERROR` | The wait group identity was not known to the runtime.
`PR_INVALID_STATE_ERROR` | The specified wait group was not empty. It had either wait receive objects or threads waiting.

#### PR_AddWaitFileDesc

Adds a receive wait descriptor to the set of those waiting for network receive.

##### Syntax

    #include <prmwait.h>

    PRStatus PR_AddWaitFileDesc (
       PRWaitGroup *group,
       PRRecvWait *desc);

##### Parameters

The function has these parameters:

`group` | A pointer to the wait group to which to add the file descriptor, or `NULL`. When `NULL`, the default group is used.
`desc` | A pointer to a valid receive wait descriptor.

##### Returns

If the operation is successful, returns `PR_SUCCESS`. Otherwise, returns `PR_FAILURE`. Retrieve the reason for the failure by calling `PR_GetError`.

##### Description

This function adds the specified receive wait descriptor to the specified wait group. The value of `group` must be either a valid group identifier as returned from `PR_CreateWaitGroup`, or `NULL`, which specifies the default group.

Completions of the wait operation are reported when you specify the same wait group in a call to `PR_WaitRecvReady`.

Ownership of the specified receive wait descriptor is temporarily passed to the runtime; the caller may not alter any portion of the object as long as the runtime has ownership. The runtime relinquishes ownership when the reference to the object is returned as a result of `PR_WaitRecvReady`.

Error codes that can be returned by `PR_GetError` when this function fails are:

`PR_INVALID_ARGUMENT_ERROR` | The `group` argument is not a valid group identifier or the `desc` argument refers to a receive descriptor that is already known by the runtime.
`PR_OUT_OF_MEMORY_ERROR` | The runtime was not able to allocate the resources required to process the request.
`PR_INVALID_STATE_ERROR` | The specified group is being destroyed.

#### PR_WaitRecvReady

Returns a completed receive wait descriptor from a wait group.

##### Syntax

    #include <prmwait.h>

    PRRecvWait* PR_WaitRecvReady(PRWaitGroup *group);

##### Parameters

The function has this parameter:

`group` | A pointer to the wait group where receive descriptors were added.

##### Returns

Returns a reference to a receive wait descriptor, or `NULL` in case of error. Retrieve the reason for the error by calling `PR_GetError`.

##### Description

This function blocks the calling thread until one of the receive wait descriptors in the specified group has completed. Only descriptors that were added to the specified group identity using `PR_AddWaitFileDesc` are returned.

The descriptor returned may have completed and have input data available, or it may have encountered some error (timeout or interrupt). Check the `outcome` field of the returned object and test it for success. If the function returns `NULL` or the `outcome` field indicates other than success, retrieve the reason for the error by calling `PR_GetError`. Possible errors are:

`PR_INVALID_ARGUMENT_ERROR` | The value of `group` does not represent a group identifier known to the runtime.
`PR_PENDING_INTERRUPT_ERROR` | If the function returned `NULL`, the call to `PR_WaitRecvReady` was interrupted by another thread. Otherwise, the descriptor was specifically canceled (see `PR_CancelWaitFileDesc`) or was a member of a wait group that was canceled (see `PR_CancelWaitGroup`).
`PR_INVALID_STATE_ERROR` | The call specified a wait group that is being destroyed.

#### PR_CancelWaitFileDesc

Cancels the wait operation for a receive wait descriptor.

##### Syntax

    #include <prmwait.h>

    PRStatus PR_CancelWaitFileDesc (
       PRWaitGroup *group,
       PRRecvWait *desc);

##### Parameters

The function has these parameters:

`group` | A pointer to a wait group, or `NULL`, which indicates the default wait group.
`desc` | A pointer to the receive wait descriptor to be canceled.

##### Return

If successful, `PR_SUCCESS`. Otherwise, returns `PR_FAILURE`. Retrieve the reason for the failure by calling `PR_GetError`.

##### Description

This function cancels operations on objects previously submitted to the runtime using `PR_AddWaitFileDesc`. If the runtime locates the specified descriptor in the specified wait group, it is marked as having failed because it was interrupted (similar to `PR_Interrupt`).

The first available thread blocked in `PR_WaitRecvReady` is made to return with the reference to the specified descriptor. The object's `outcome` field indicates that the operation was canceled.

If the function returns a value of `PR_FAILURE`, retrieve the exact cause of the failure by calling `PR_GetError`. Possible errors are:

`PR_INVALID_ARGUMENT_ERROR` | The `group` identity was not known to the runtime, or the referenced object `desc` could not be located in the set of receive wait descriptors associated with the `group`.
`PR_INVALID_STATE_ERROR` | The `group` is being destroyed.

#### PR_CancelWaitGroup

Cancels all pending wait operations for a wait group.

##### Syntax

    #include <prmwait.h>

    PRRecvWait* PR_CancelWaitGroup (PRWaitGroup *group);

##### Parameters

The function has this parameter:

`group` | A pointer to the wait group to be canceled.

##### Returns

`A` pointer to a wait receive object, or `NULL` if no objects are contained in the group or in case of error. Retrieve the reason for the failure by calling `PR_GetError`.

##### Description

This function cancels all the operations registered with the specified wait group.

Each successive call returns a pointer to a receive wait descriptor that was previously registered with the specified group using `PR_AddWaitFileDesc`. The returned object's `outcome` field contains the indication that the operation had been canceled.

If no wait objects are associated with the specified wait group, the function returns `NULL`. Call this function in a loop until it returns `NULL` to reclaim all the wait objects from a wait group, prior to calling `PR_DestroyWaitGroup`.

When the function returns `NULL`, retrieve the exact cause by calling `PR_GetError`. Possible errors are:

`PR_INVALID_ARGUMENT_ERROR` | The value of the `group` argument was not the identity of a valid wait group.
`PR_GROUP_EMPTY_ERROR` | The group's wait receive set is empty. This is the natural termination of the loop used to destroy a wait group.

Previous Contents Next

Last Updated May 18, 2001