Home | History | Annotate | Download | only in nspr
      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /*
      3  * The contents of this file are subject to the Mozilla Public
      4  * License Version 1.1 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of
      6  * the License at http://www.mozilla.org/MPL/
      7  *
      8  * Software distributed under the License is distributed on an "AS
      9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
     10  * implied. See the License for the specific language governing
     11  * rights and limitations under the License.
     12  *
     13  * The Original Code is the Netscape Portable Runtime (NSPR).
     14  *
     15  * The Initial Developer of the Original Code is Netscape
     16  * Communications Corporation.  Portions created by Netscape are
     17  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
     18  * Rights Reserved.
     19  *
     20  * Contributor(s):
     21  *
     22  * Alternatively, the contents of this file may be used under the
     23  * terms of the GNU General Public License Version 2 or later (the
     24  * "GPL"), in which case the provisions of the GPL are applicable
     25  * instead of those above.  If you wish to allow use of your
     26  * version of this file only under the terms of the GPL and not to
     27  * allow others to use your version of this file under the MPL,
     28  * indicate your decision by deleting the provisions above and
     29  * replace them with the notice and other provisions required by
     30  * the GPL.  If you do not delete the provisions above, a recipient
     31  * may use your version of this file under either the MPL or the
     32  * GPL.
     33  */
     34 
     35 #if defined(_PRMWAIT_H)
     36 #else
     37 #define _PRMWAIT_H
     38 
     39 #include "prio.h"
     40 #include "prtypes.h"
     41 #include "prclist.h"
     42 
     43 PR_BEGIN_EXTERN_C
     44 
     45 /********************************************************************************/
     46 /********************************************************************************/
     47 /********************************************************************************/
     48 /******************************       WARNING        ****************************/
     49 /********************************************************************************/
     50 /**************************** This is work in progress. *************************/
     51 /************************** Do not make any assumptions *************************/
     52 /************************** about the stability of this *************************/
     53 /************************** API or the underlying imple- ************************/
     54 /************************** mentation.                   ************************/
     55 /********************************************************************************/
     56 /********************************************************************************/
     57 
     58 /*
     59 ** STRUCTURE:   PRWaitGroup
     60 ** DESCRIPTION:
     61 **      The client may define several wait groups in order to semantically
     62 **      tie a collection of file descriptors for a single purpose. This allows
     63 **      easier dispatching of threads that returned with active file descriptors
     64 **      from the wait function.
     65 */
     66 typedef struct PRWaitGroup PRWaitGroup;
     67 
     68 /*
     69 ** ENUMERATION: PRMWStatus
     70 ** DESCRIPTION:
     71 **      This enumeration is used to indicate the completion status of
     72 **      a receive wait object. Generally stated, a positive value indicates
     73 **      that the operation is not yet complete. A zero value indicates
     74 **      success (similar to PR_SUCCESS) and any negative value is an
     75 **      indication of failure. The reason for the failure can be retrieved
     76 **      by calling PR_GetError().
     77 **
     78 **  PR_MW_PENDING       The operation is still pending. None of the other
     79 **                      fields of the object are currently valid.
     80 **  PR_MW_SUCCESS       The operation is complete and it was successful.
     81 **  PR_MW_FAILURE       The operation failed. The reason for the failure
     82 **                      can be retrieved by calling PR_GetError().
     83 **  PR_MW_TIMEOUT       The amount of time allowed for by the object's
     84 **                      'timeout' field has expired w/o the operation
     85 **                      otherwise coming to closure.
     86 **  PR_MW_INTERRUPT     The operation was cancelled, either by the client
     87 **                      calling PR_CancelWaitFileDesc() or destroying the
     88 **                      entire wait group (PR_DestroyWaitGroup()).
     89 */
     90 typedef enum PRMWStatus
     91 {
     92     PR_MW_PENDING = 1,
     93     PR_MW_SUCCESS = 0,
     94     PR_MW_FAILURE = -1,
     95     PR_MW_TIMEOUT = -2,
     96     PR_MW_INTERRUPT = -3
     97 } PRMWStatus;
     98 
     99 /*
    100 ** STRUCTURE:   PRMemoryDescriptor
    101 ** DESCRIPTION:
    102 **      THis is a descriptor for an interval of memory. It contains a
    103 **      pointer to the first byte of that memory and the length (in
    104 **      bytes) of the interval.
    105 */
    106 typedef struct PRMemoryDescriptor
    107 {
    108     void *start;                /* pointer to first byte of memory */
    109     PRSize length;              /* length (in bytes) of memory interval */
    110 } PRMemoryDescriptor;
    111 
    112 /*
    113 ** STRUCTURE:   PRMWaitClientData
    114 ** DESCRIPTION:
    115 **      An opague stucture for which a client MAY give provide a concrete
    116 **      definition and associate with a receive descriptor. The NSPR runtime
    117 **      does not manage this field. It is completely up to the client.
    118 */
    119 typedef struct PRMWaitClientData PRMWaitClientData;
    120 
    121 /*
    122 ** STRUCTURE:   PRRecvWait
    123 ** DESCRIPTION:
    124 **      A receive wait object contains the file descriptor that is subject
    125 **      to the wait and the amount of time (beginning epoch established
    126 **      when the object is presented to the runtime) the the channel should
    127 **      block before abandoning the process.
    128 **
    129 **      The success of the wait operation will be noted in the object's
    130 **      'outcome' field. The fields are not valid when the NSPR runtime
    131 **      is in possession of the object.
    132 **
    133 **      The memory descriptor describes an interval of writable memory
    134 **      in the caller's address space where data from an initial read
    135 **      can be placed. The description may indicate a null interval.
    136 */
    137 typedef struct PRRecvWait
    138 {
    139     PRCList internal;           /* internal runtime linkages */
    140 
    141     PRFileDesc *fd;             /* file descriptor associated w/ object */
    142     PRMWStatus outcome;         /* outcome of the current/last operation */
    143     PRIntervalTime timeout;     /* time allowed for entire operation */
    144 
    145     PRInt32 bytesRecv;          /* number of bytes transferred into buffer */
    146     PRMemoryDescriptor buffer;  /* where to store first segment of input data */
    147     PRMWaitClientData *client;  /* pointer to arbitrary client defined data */
    148 } PRRecvWait;
    149 
    150 /*
    151 ** STRUCTURE:   PRMWaitEnumerator
    152 ** DESCRIPTION:
    153 **      An enumeration object is used to store the state of an existing
    154 **      enumeration over a wait group. The opaque object must be allocated
    155 **      by the client and the reference presented on each call to the
    156 **      pseudo-stateless enumerator. The enumeration objects are sharable
    157 **      only in serial fashion.
    158 */
    159 typedef struct PRMWaitEnumerator PRMWaitEnumerator;
    160 
    161 
    162 /*
    163 ** FUNCTION:    PR_AddWaitFileDesc
    164 ** DESCRIPTION:
    165 **      This function will effectively add a file descriptor to the
    166 **      list of those waiting for network receive. The new descriptor
    167 **      will be semantically tied to the wait group specified.
    168 **
    169 **      The ownership for the storage pointed to by 'desc' is temporarily
    170 **      passed over the the NSPR runtime. It will be handed back by the
    171 **      function PR_WaitRecvReady().
    172 **
    173 **  INPUTS
    174 **      group       A reference to a PRWaitGroup or NULL. Wait groups are
    175 **                  created by calling PR_CreateWaitGroup() and are used
    176 **                  to semantically group various file descriptors by the
    177 **                  client's application.
    178 **      desc        A reference to a valid PRRecvWait. The object of the
    179 **                  reference must be preserved and not be modified
    180 **                  until its ownership is returned to the client.
    181 **  RETURN
    182 **      PRStatus    An indication of success. If equal to PR_FAILUE details
    183 **                  of the failure are avaiable via PR_GetError().
    184 **
    185 **  ERRORS
    186 **      PR_INVALID_ARGUMENT_ERROR
    187 **                  Invalid 'group' identifier or duplicate 'desc' object.
    188 **      PR_OUT_OF_MEMORY_ERROR
    189 **                  Insuffient memory for internal data structures.
    190 **      PR_INVALID_STATE_ERROR
    191 **                  The group is being destroyed.
    192 */
    193 NSPR_API(PRStatus) PR_AddWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc);
    194 
    195 /*
    196 ** FUNCTION:    PR_WaitRecvReady
    197 ** DESCRIPTION:
    198 **      PR_WaitRecvReady will block the calling thread until one of the
    199 **      file descriptors that have been added via PR_AddWaitFileDesc is
    200 **      available for input I/O.
    201 **  INPUT
    202 **      group       A pointer to a valid PRWaitGroup or NULL (the null
    203 **                  group. The function will block the caller until a
    204 **                  channel from the wait group becomes ready for receive
    205 **                  or there is some sort of error.
    206 **  RETURN
    207 **      PRReciveWait
    208 **                  When the caller is resumed it is either returned a
    209 **                  valid pointer to a previously added receive wait or
    210 **                  a NULL. If the latter, the function has terminated
    211 **                  for a reason that can be determined by calling
    212 **                  PR_GetError().
    213 **                  If a valid pointer is returned, the reference is to the
    214 **                  file descriptor contained in the receive wait object.
    215 **                  The outcome of the wait operation may still fail, and
    216 **                  if it has, that fact will be noted in the object's
    217 **                  outcome field. Details can be retrieved from PR_GetError().
    218 **
    219 **  ERRORS
    220 **      PR_INVALID_ARGUMENT_ERROR
    221 **                  The 'group' is not known by the runtime.
    222 **      PR_PENDING_INTERRUPT_ERROR
    223                     The thread was interrupted.
    224 **      PR_INVALID_STATE_ERROR
    225 **                  The group is being destroyed.
    226 */
    227 NSPR_API(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group);
    228 
    229 /*
    230 ** FUNCTION:    PR_CancelWaitFileDesc
    231 ** DESCRIPTION:
    232 **      PR_CancelWaitFileDesc is provided as a means for cancelling operations
    233 **      on objects previously submitted by use of PR_AddWaitFileDesc(). If
    234 **      the runtime knows of the object, it will be marked as having failed
    235 **      because it was interrupted (similar to PR_Interrupt()). The first
    236 **      available thread waiting on the group will be made to return the
    237 **      PRRecvWait object with the outcome noted.
    238 **
    239 **  INPUTS
    240 **      group       The wait group under which the wait receive object was
    241 **                  added.
    242 **      desc        A pointer to the wait receive object that is to be
    243 **                  cancelled.
    244 **  RETURN
    245 **      PRStatus    If the wait receive object was located and associated
    246 **                  with the specified wait group, the status returned will
    247 **                  be PR_SUCCESS. There is still a race condition that would
    248 **                  permit the offected object to complete normally, but it
    249 **                  is assured that it will complete in the near future.
    250 **                  If the receive object or wait group are invalid, the
    251 **                  function will return with a status of PR_FAILURE.
    252 **
    253 **  ERRORS
    254 **      PR_INVALID_ARGUMENT_ERROR
    255 **                  The 'group' argument is not recognized as a valid group.
    256 **      PR_COLLECTION_EMPTY_ERROR
    257 **                  There are no more receive wait objects in the group's
    258 **                  collection.
    259 **      PR_INVALID_STATE_ERROR
    260 **                  The group is being destroyed.
    261 */
    262 NSPR_API(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc);
    263 
    264 /*
    265 ** FUNCTION:    PR_CancelWaitGroup
    266 ** DESCRIPTION:
    267 **      PR_CancelWaitGroup is provided as a means for cancelling operations
    268 **      on objects previously submitted by use of PR_AddWaitFileDesc(). Each
    269 **      successive call will return a pointer to a PRRecvWait object that
    270 **      was previously registered via PR_AddWaitFileDesc(). If no wait
    271 **      objects are associated with the wait group, a NULL will be returned.
    272 **      This function should be called in a loop until a NULL is returned
    273 **      to reclaim all the wait objects prior to calling PR_DestroyWaitGroup().
    274 **
    275 **  INPUTS
    276 **      group       The wait group under which the wait receive object was
    277 **                  added.
    278 **  RETURN
    279 **      PRRecvWait* If the wait group is valid and at least one receive wait
    280 **                  object is present in the group, that object will be
    281 **                  marked as PR_MW_INTERRUPT'd and removed from the group's
    282 **                  queues. Otherwise a NULL will be returned and the reason
    283 **                  for the NULL may be retrieved by calling PR_GetError().
    284 **
    285 **  ERRORS
    286 **      PR_INVALID_ARGUMENT_ERROR
    287 **      PR_GROUP_EMPTY_ERROR
    288 */
    289 NSPR_API(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group);
    290 
    291 /*
    292 ** FUNCTION:    PR_CreateWaitGroup
    293 ** DESCRIPTION:
    294 **      A wait group is an opaque object that a client may create in order
    295 **      to semantically group various wait requests. Each wait group is
    296 **      unique, including the default wait group (NULL). A wait request
    297 **      that was added under a wait group will only be serviced by a caller
    298 **      that specified the same wait group.
    299 **
    300 **  INPUT
    301 **      size        The size of the hash table to be used to contain the
    302 **                  receive wait objects. This is just the initial size.
    303 **                  It will grow as it needs to, but to avoid that hassle
    304 **                  one can suggest a suitable size initially. It should
    305 **                  be ~30% larger than the maximum number of receive wait
    306 **                  objects expected.
    307 **  RETURN
    308 **      PRWaitGroup If successful, the function will return a pointer to an
    309 **                  object that was allocated by and owned by the runtime.
    310 **                  The reference remains valid until it is explicitly destroyed
    311 **                  by calling PR_DestroyWaitGroup().
    312 **
    313 **  ERRORS
    314 **      PR_OUT_OF_MEMORY_ERROR
    315 */
    316 NSPR_API(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size);
    317 
    318 /*
    319 ** FUNCTION:    PR_DestroyWaitGroup
    320 ** DESCRIPTION:
    321 **      Undo the effects of PR_CreateWaitGroup(). Any receive wait operations
    322 **      on the group will be treated as if the each had been the target of a
    323 **      PR_CancelWaitFileDesc().
    324 **
    325 **  INPUT
    326 **      group       Reference to a wait group previously allocated using
    327 **                  PR_CreateWaitGroup().
    328 **  RETURN
    329 **      PRStatus    Will be PR_SUCCESS if the wait group was valid and there
    330 **                  are no receive wait objects in that group. Otherwise
    331 **                  will indicate PR_FAILURE.
    332 **
    333 **  ERRORS
    334 **      PR_INVALID_ARGUMENT_ERROR
    335 **                  The 'group' argument does not reference a known object.
    336 **      PR_INVALID_STATE_ERROR
    337 **                  The group still contains receive wait objects.
    338 */
    339 NSPR_API(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group);
    340 
    341 /*
    342 ** FUNCTION:    PR_CreateMWaitEnumerator
    343 ** DESCRIPTION:
    344 **      The PR_CreateMWaitEnumerator() function returns a reference to an
    345 **      opaque PRMWaitEnumerator object. The enumerator object is required
    346 **      as an argument for each successive call in the stateless enumeration
    347 **      of the indicated wait group.
    348 **
    349 **      group       The wait group that the enumeration is intended to
    350 **                  process. It may be be the default wait group (NULL).
    351 ** RETURN
    352 **      PRMWaitEnumerator* group
    353 **                  A reference to an object that will be used to store
    354 **                  intermediate state of enumerations.
    355 ** ERRORS
    356 **      Errors are indicated by the function returning a NULL.
    357 **      PR_INVALID_ARGUMENT_ERROR
    358 **                  The 'group' argument does not reference a known object.
    359 **      PR_OUT_OF_MEMORY_ERROR
    360 */
    361 NSPR_API(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group);
    362 
    363 /*
    364 ** FUNCTION:    PR_DestroyMWaitEnumerator
    365 ** DESCRIPTION:
    366 **      Destroys the object created by PR_CreateMWaitEnumerator(). The reference
    367 **      used as an argument becomes invalid.
    368 **
    369 ** INPUT
    370 **      PRMWaitEnumerator* enumerator
    371 **          The PRMWaitEnumerator object to destroy.
    372 ** RETURN
    373 **      PRStatus
    374 **          PR_SUCCESS if successful, PR_FAILURE otherwise.
    375 ** ERRORS
    376 **      PR_INVALID_ARGUMENT_ERROR
    377 **                  The enumerator is invalid.
    378 */
    379 NSPR_API(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator);
    380 
    381 /*
    382 ** FUNCTION:    PR_EnumerateWaitGroup
    383 ** DESCRIPTION:
    384 **      PR_EnumerateWaitGroup is a thread safe enumerator over a wait group.
    385 **      Each call to the enumerator must present a valid PRMWaitEnumerator
    386 **      rererence and a pointer to the "previous" element returned from the
    387 **      enumeration process or a NULL.
    388 **
    389 **      An enumeration is started by passing a NULL as the "previous" value.
    390 **      Subsequent calls to the enumerator must pass in the result of the
    391 **      previous call. The enumeration end is signaled by the runtime returning
    392 **      a NULL as the result.
    393 **
    394 **      Modifications to the content of the wait group are allowed during
    395 **      an enumeration. The effect is that the enumeration may have to be
    396 **      "reset" and that may result in duplicates being returned from the
    397 **      enumeration.
    398 **
    399 **      An enumeration may be abandoned at any time. The runtime is not
    400 **      keeping any state, so there are no issues in that regard.
    401 */
    402 NSPR_API(PRRecvWait*) PR_EnumerateWaitGroup(
    403     PRMWaitEnumerator *enumerator, const PRRecvWait *previous);
    404 
    405 PR_END_EXTERN_C
    406 
    407 #endif /* defined(_PRMWAIT_H) */
    408 
    409 /* prmwait.h */
    410