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