|
|
[Contents] [Previous]
[Next][Last]
Appendix A
Multiwait Receive
This section describes an helper API that clients might find useful
in certain circumstances. The multiwait function allows its clients
to service an arbitrary number of network file descriptors with a relatively
small number of threads. This is trading off the simplicity of fully synchronous
I/O for a limited amount of asynchronous behavior. Its premise is that
the connections are mostly idle, that they in fact spend most of
their time waiting for network input.
This premise is based on the anticipated behavior of the passive partner
in a client/server relationship (i.e., the server). 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) than the
time spent in formulating and delivering the response, then this function
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. Different groups
may be defined by the client, allowing separate pools of threads to be
associated with different collections of file descriptors.
Multiwait types
The multiwait receive interface defines and uses the following types.
PRWaitGroup
The client may 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.
typedef struct PRWaitGroup PRWaitGroup;
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
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().
typedef enum PRMWStatus
{
PR_MW_PENDING = 1,
PR_MW_SUCCESS = 0,
PR_MW_FAILURE = -1,
PR_MW_TIMEOUT = -2,
PR_MW_INTERRUPT = -3
} PRMWStatus;
| PR_MW_PENDING |
The operation is still pending. None of the other fields of the object
are 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 w/o the operation otherwise coming to closure. |
| PR_MW_INTERRUPT |
The operation was canceled, either by the client calling PR_CancelWaitFileDesc()
or destroying the entire wait group (PR_DestroyWaitGroup()). |
PRMemoryDescriptor
This is a descriptor for an interval of memory. It contains a pointer to
the first byte of that memory and the length (in bytes) of the interval.
typedef struct PRMemoryDescriptor
{
void *start;
PRSize length;
} PRMemoryDescriptor;
| start |
This is the address of the first byte of memory that the descriptor
defines. |
| length |
The length of the memory in bytes. |
PRRecvWait
A receive wait object contains the file descriptor that is subject to the
wait and the amount of time (beginning epoch is established when the object
is presented to the runtime) the channel should block before abandoning
the process.
The success of the wait operation will be 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 may indicate a null interval.
typedef struct PRRecvWait
{
PRCList internal;
PRFileDesc *fd;
PRMWStatus outcome;
PRIntervalTime timeout;
PRInt32 bytesRecv;
PRMemoryDescriptor buffer;
} PRRecvWait;
| 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 pending when the object is first accepted.
As long as the value remains pending, none of the other fields are
assumed valid. |
| bytesRecv |
When the operation is complete, this field will contain 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 may be indicated. |
| buffer |
A description of the memory reserved by the client in which to store
data arriving from the network. This descriptor may indicate an empty buffer,
which implies that the file descriptor is receive ready only. |
Multiwait functions
PR_CreateWaitGroup
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 (NULL). A wait request that was added under a
wait group will only be serviced by a call to PR_WaitRecvReady()
that specified the same wait group.
PRWaitGroup* PR_CreateWaitGroup(PRInt32 size_hint);
Parameters
| 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. |
Result
If successful, the function will return 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 the function fails it will return a NULL. The reason for
the NULL return can be learned by calling PR_GetError().
The only reason for failure is a heap allocation failure.
PR_DestroyWaitGroup
To undo the effects of PR_CreateWaitGroup(),
a client must call PR_DestroyWaitGroup().
The wait group must be not contain any receive wait objects. Those must
have all been cleared using the PR_CancelWaitFileDesc()
function.
PRStatus PR_DestroyWaitGroup(PRWaitGroup *group);
Parameters
| 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. |
Result
If the wait group can be successfully destroyed, the return value will
be PR_SUCCESS. If not, the reason for the failure can be learned
by calling PR_GetError().
| 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. That is it had either wait
receive objects or threads waiting. |
PR_AddWaitFileDesc
This function will effectively add a file descriptor to the set of those
waiting for network receive.
PRStatus PR_AddWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc);
Parameters
| group |
The object referenced by the desc will be associated with
this group. The value of group must be either a valid group identifier
that was acquired as a result of PR_CreateWaitGroup()
or NULL implying the default group association. Completions
of the wait operation will only be reported to callers that specify the
same wait group. |
| desc |
A pointer to a valid receive wait descriptor. Ownership of the storage
is temporarily passed to the runtime; the caller may not alter any portion
of the object as long as the runtime has ownership. Ownership will be relinquished
by the runtime when the reference to the object is returned as a result
of PR_WaitRecvReady(). |
Result
If the operation is successful, a PR_SUCESS value will be returned.
If a PR_FAILURE status is returned, one of the following errors
has occurred. Which error may be determined by calling PR_GetError().
| PR_INVALID_ARGUMENT_ERROR |
The group argument does not contain the identify of a valid
group identifier or the desc argument contains a reference to
a receive descriptor that is already known my 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 group specified is being destroyed. |
PR_WaitRecvReady
PR_WaitRecvReady() will block the calling thread until
one of the file descriptors that have been added via PR_AddWaitFileDesc()
has complete. The descriptor returned may have competed and have input
data available or it may have encountered some error (timeout or interrupt).
Only descriptors that were added with the same group identity will be returned.
PRRecvWait* PR_WaitRecvReady(PRWaitGroup *group);
Parameters
| group |
The identity of the wait group where receive descriptors were added. |
Result
The result of PR_WaitRecvReady() is a reference to a wait
descriptor. If the returned value is NULL and error was encountered.
If the result is not NULL the caller must check the status
field of the returned object and test it for success. If the result is
NULL or the status field indicates other than success,
the reason for the error is available by calling PR_GetError().
| PR_INVALID_ARGUMENT_ERROR |
The value of group does not represent a group identifier known
to the runtime. |
| PR_PENDING_INTERRUPT_ERROR |
If the result is 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 destroyed (see PR_CancelWaitGroup()). |
| PR_INVALID_STATE_ERROR |
The call specified a wait group that is being destroyed. |
PR_CancelWaitFileDesc
PR_CancelWaitFileDesc() is provided as a means for canceling
operations on objects previously submitted to the runtime by use of PR_AddWaitFileDesc().
If the runtime knows of the object, it will be marked as having failed
because it was interrupted (similar to PR_Interrupt()).
The first available thread waiting on the group will be made to return
the PRRecvWait object with the
reason noted in the object's outcome field.
PRStatus PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc);
Parameters
| group |
A valid wait group identifier or NULL that identifies the
wait group in which the desc object is currently waiting. |
| desc |
A reference to the particular wait receive descriptor that is to be
canceled. |
Return
If the function returns with a value of PR_SUCCESS, the target
descriptor was located and marked for cancellation. The first available
thread blocked in PR_WaitRecvReady()
will be made to return with the reference to the object. The object's outcome
field will indicate that the operation was canceled.
If the function returns a value of PR_FAILURE, the cause may
be one of several reasons. The exact cause of the failure can be determined
by calling PR_GetError().
| PR_INVALID_ARGUMENT_ERROR |
The group identity was not known to the runtime. |
| PR_INVALID_STATE_ERROR |
The group is being destroyed. |
| ???? |
The referenced object could not be located in the set of receive wait
descriptors associated with the group. |
PR_CancelWaitGroup
PR_CancelWaitGroup() is provided as a means for canceling
all the operations registered with a specific wait group. Each successive
call will return a pointer to a PRRecvWait object that was previously
registered via PR_AddWaitFileDesc().
If no wait objects are associated with the wait group, a NULL
will be returned. This function should be called in a loop until a NULL
is returned to reclaim all the wait objects prior to calling PR_DestroyWaitGroup().
PRRecvWait* PR_CancelWaitGroup(PRWaitGroup *group);
Parameters
| group |
The identity of the wait group that is to have all pending wait receive
objects canceled. |
Return
PR_CancelWaitGroup() returns a pointer to a wait receive
object or a NULL. If not NULL the object's outcome field
will contain the indication that the operation had been canceled. If it
is NULL, the actual reason must be learned by calling PR_GetError().
| 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. |
[Contents] [Previous]
[Next][Last]
Last Updated: Wed Jul 15 11:15:14 PDT 1998
Copyright © 1998 Netscape
Communications Corporation
|