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