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
14PR_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*/
37typedef 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*/
61typedef 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*/
77typedef 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*/
90typedef 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*/
108typedef 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*/
130typedef 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*/
164NSPR_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*/
198NSPR_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*/
233NSPR_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*/
260NSPR_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*/
287NSPR_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*/
310NSPR_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*/
332NSPR_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*/
350NSPR_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*/
373NSPR_API(PRRecvWait*) PR_EnumerateWaitGroup(
374 PRMWaitEnumerator *enumerator, const PRRecvWait *previous);
375
376PR_END_EXTERN_C
377
378#endif /* defined(_PRMWAIT_H) */
379
380/* prmwait.h */
381

source code of include/nspr/prmwait.h