/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #if defined(_PRMWAIT_H) #else #define _PRMWAIT_H #include "prio.h" #include "prtypes.h" #include "prclist.h" PR_BEGIN_EXTERN_C /********************************************************************************/ /********************************************************************************/ /********************************************************************************/ /****************************** WARNING ****************************/ /********************************************************************************/ /**************************** This is work in progress. *************************/ /************************** Do not make any assumptions *************************/ /************************** about the stability of this *************************/ /************************** API or the underlying imple- ************************/ /************************** mentation. ************************/ /********************************************************************************/ /********************************************************************************/ /* ** STRUCTURE: PRWaitGroup ** DESCRIPTION: ** 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; /* ** ENUMERATION: PRMWStatus ** DESCRIPTION: ** This 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 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 cancelled, either by the client ** calling PR_CancelWaitFileDesc() or destroying the ** entire wait group (PR_DestroyWaitGroup()). */ typedef enum PRMWStatus { PR_MW_PENDING = 1, PR_MW_SUCCESS = 0, PR_MW_FAILURE = -1, PR_MW_TIMEOUT = -2, PR_MW_INTERRUPT = -3 } PRMWStatus; /* ** STRUCTURE: PRMemoryDescriptor ** DESCRIPTION: ** 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; /* pointer to first byte of memory */ PRSize length; /* length (in bytes) of memory interval */ } PRMemoryDescriptor; /* ** STRUCTURE: PRMWaitClientData ** DESCRIPTION: ** An opague stucture for which a client MAY give provide a concrete ** definition and associate with a receive descriptor. The NSPR runtime ** does not manage this field. It is completely up to the client. */ typedef struct PRMWaitClientData PRMWaitClientData; /* ** STRUCTURE: PRRecvWait ** DESCRIPTION: ** A receive wait object contains the file descriptor that is subject ** to the wait and the amount of time (beginning epoch established ** when the object is presented to the runtime) the 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; /* internal runtime linkages */ PRFileDesc *fd; /* file descriptor associated w/ object */ PRMWStatus outcome; /* outcome of the current/last operation */ PRIntervalTime timeout; /* time allowed for entire operation */ PRInt32 bytesRecv; /* number of bytes transferred into buffer */ PRMemoryDescriptor buffer; /* where to store first segment of input data */ PRMWaitClientData *client; /* pointer to arbitrary client defined data */ } PRRecvWait; /* ** STRUCTURE: PRMWaitEnumerator ** DESCRIPTION: ** An enumeration object is used to store the state of an existing ** enumeration over a wait group. The opaque object must be allocated ** by the client and the reference presented on each call to the ** pseudo-stateless enumerator. The enumeration objects are sharable ** only in serial fashion. */ typedef struct PRMWaitEnumerator PRMWaitEnumerator; /* ** FUNCTION: PR_AddWaitFileDesc ** DESCRIPTION: ** This function will effectively add a file descriptor to the ** list of those waiting for network receive. The new descriptor ** will be semantically tied to the wait group specified. ** ** The ownership for the storage pointed to by 'desc' is temporarily ** passed over the the NSPR runtime. It will be handed back by the ** function PR_WaitRecvReady(). ** ** INPUTS ** group A reference to a PRWaitGroup or NULL. Wait groups are ** created by calling PR_CreateWaitGroup() and are used ** to semantically group various file descriptors by the ** client's application. ** desc A reference to a valid PRRecvWait. The object of the ** reference must be preserved and not be modified ** until its ownership is returned to the client. ** RETURN ** PRStatus An indication of success. If equal to PR_FAILUE details ** of the failure are avaiable via PR_GetError(). ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** Invalid 'group' identifier or duplicate 'desc' object. ** PR_OUT_OF_MEMORY_ERROR ** Insuffient memory for internal data structures. ** PR_INVALID_STATE_ERROR ** The group is being destroyed. */ PR_EXTERN(PRStatus) PR_AddWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc); /* ** FUNCTION: PR_WaitRecvReady ** DESCRIPTION: ** PR_WaitRecvReady will block the calling thread until one of the ** file descriptors that have been added via PR_AddWaitFileDesc is ** available for input I/O. ** INPUT ** group A pointer to a valid PRWaitGroup or NULL (the null ** group. The function will block the caller until a ** channel from the wait group becomes ready for receive ** or there is some sort of error. ** RETURN ** PRReciveWait ** When the caller is resumed it is either returned a ** valid pointer to a previously added receive wait or ** a NULL. If the latter, the function has terminated ** for a reason that can be determined by calling ** PR_GetError(). ** If a valid pointer is returned, the reference is to the ** file descriptor contained in the receive wait object. ** The outcome of the wait operation may still fail, and ** if it has, that fact will be noted in the object's ** outcome field. Details can be retrieved from PR_GetError(). ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The 'group' is not known by the runtime. ** PR_PENDING_INTERRUPT_ERROR The thread was interrupted. ** PR_INVALID_STATE_ERROR ** The group is being destroyed. */ PR_EXTERN(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group); /* ** FUNCTION: PR_CancelWaitFileDesc ** DESCRIPTION: ** PR_CancelWaitFileDesc is provided as a means for cancelling operations ** on objects previously submitted 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 outcome noted. ** ** INPUTS ** group The wait group under which the wait receive object was ** added. ** desc A pointer to the wait receive object that is to be ** cancelled. ** RETURN ** PRStatus If the wait receive object was located and associated ** with the specified wait group, the status returned will ** be PR_SUCCESS. There is still a race condition that would ** permit the offected object to complete normally, but it ** is assured that it will complete in the near future. ** If the receive object or wait group are invalid, the ** function will return with a status of PR_FAILURE. ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The 'group' argument is not recognized as a valid group. ** PR_COLLECTION_EMPTY_ERROR ** There are no more receive wait objects in the group's ** collection. ** PR_INVALID_STATE_ERROR ** The group is being destroyed. */ PR_EXTERN(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc); /* ** FUNCTION: PR_CancelWaitGroup ** DESCRIPTION: ** PR_CancelWaitGroup is provided as a means for cancelling operations ** on objects previously submitted by use of PR_AddWaitFileDesc(). 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(). ** ** INPUTS ** group The wait group under which the wait receive object was ** added. ** RETURN ** PRRecvWait* If the wait group is valid and at least one receive wait ** object is present in the group, that object will be ** marked as PR_MW_INTERRUPT'd and removed from the group's ** queues. Otherwise a NULL will be returned and the reason ** for the NULL may be retrieved by calling PR_GetError(). ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** PR_GROUP_EMPTY_ERROR */ PR_EXTERN(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group); /* ** FUNCTION: PR_CreateWaitGroup ** DESCRIPTION: ** A wait group is an opaque object that a client may create in order ** to semantically group various wait requests. 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 caller ** that specified the same wait group. ** ** INPUT ** size The size of the hash table to be used to contain the ** receive wait objects. This is just the initial size. ** It will grow as it needs to, but to avoid that hassle ** one can suggest a suitable size initially. It should ** be ~30% larger than the maximum number of receive wait ** objects expected. ** RETURN ** PRWaitGroup If successful, the function will return a pointer to an ** object that was allocated by and owned by the runtime. ** The reference remains valid until it is explicitly destroyed ** by calling PR_DestroyWaitGroup(). ** ** ERRORS ** PR_OUT_OF_MEMORY_ERROR */ PR_EXTERN(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size); /* ** FUNCTION: PR_DestroyWaitGroup ** DESCRIPTION: ** Undo the effects of PR_CreateWaitGroup(). Any receive wait operations ** on the group will be treated as if the each had been the target of a ** PR_CancelWaitFileDesc(). ** ** INPUT ** group Reference to a wait group previously allocated using ** PR_CreateWaitGroup(). ** RETURN ** PRStatus Will be PR_SUCCESS if the wait group was valid and there ** are no receive wait objects in that group. Otherwise ** will indicate PR_FAILURE. ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The 'group' argument does not reference a known object. ** PR_INVALID_STATE_ERROR ** The group still contains receive wait objects. */ PR_EXTERN(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group); /* ** FUNCTION: PR_CreateMWaitEnumerator ** DESCRIPTION: ** The PR_CreateMWaitEnumerator() function returns a reference to an ** opaque PRMWaitEnumerator object. The enumerator object is required ** as an argument for each successive call in the stateless enumeration ** of the indicated wait group. ** ** group The wait group that the enumeration is intended to ** process. It may be be the default wait group (NULL). ** RETURN ** PRMWaitEnumerator* group ** A reference to an object that will be used to store ** intermediate state of enumerations. ** ERRORS ** Errors are indicated by the function returning a NULL. ** PR_INVALID_ARGUMENT_ERROR ** The 'group' argument does not reference a known object. ** PR_OUT_OF_MEMORY_ERROR */ PR_EXTERN(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group); /* ** FUNCTION: PR_DestroyMWaitEnumerator ** DESCRIPTION: ** Destroys the object created by PR_CreateMWaitEnumerator(). The reference ** used as an argument becomes invalid. ** ** INPUT ** PRMWaitEnumerator* enumerator ** The PRMWaitEnumerator object to destroy. ** RETURN ** PRStatus ** PR_SUCCESS if successful, PR_FAILURE otherwise. ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The enumerator is invalid. */ PR_EXTERN(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator); /* ** FUNCTION: PR_EnumerateWaitGroup ** DESCRIPTION: ** PR_EnumerateWaitGroup is a thread safe enumerator over a wait group. ** Each call to the enumerator must present a valid PRMWaitEnumerator ** rererence and a pointer to the "previous" element returned from the ** enumeration process or a NULL. ** ** An enumeration is started by passing a NULL as the "previous" value. ** Subsequent calls to the enumerator must pass in the result of the ** previous call. The enumeration end is signaled by the runtime returning ** a NULL as the result. ** ** Modifications to the content of the wait group are allowed during ** an enumeration. The effect is that the enumeration may have to be ** "reset" and that may result in duplicates being returned from the ** enumeration. ** ** An enumeration may be abandoned at any time. The runtime is not ** keeping any state, so there are no issues in that regard. */ PR_EXTERN(PRRecvWait*) PR_EnumerateWaitGroup( PRMWaitEnumerator *enumerator, const PRRecvWait *previous); PR_END_EXTERN_C #endif /* defined(_PRMWAIT_H) */ /* prmwait.h */