Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcasync.h
1 /*
2
3   silcasync.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2005 - 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 /****h* silcutil/SILC Async Operation Interface
21  *
22  * DESCRIPTION
23  *
24  * SILC Async Operation API is an interface that can be used to control
25  * asynchronous operations.  All functions that take callback as argument
26  * should return SilcAsyncOperation context.  That context then can be
27  * used to control, such as, abort the asynchronous operation.  Using
28  * SILC Async Operation API, asynchronous functions can be controlled
29  * and aborted safely.
30  *
31  * The SILC Async Operation API is divided in two levels; the underlaying
32  * operation level that implements the asynchronous operation, and the
33  * upper layer that can control the asynchronous operation.  The operation
34  * layer must guarantee that if the upper layer aborts the asynchronous
35  * operation, no callback function will be called back to the upper layer.
36  * This must be remembered when implementing the operation layer.
37  *
38  * EXAMPLE
39  *
40  * SilcAsyncOperation async_call(Callback callback, void *cb_context)
41  * {
42  *   SilcAsyncOperation op;
43  *   OpContext ctx;
44  *
45  *   // Allocate async operation so that caller can control us, like abort
46  *   op = silc_async_alloc(async_call_abort, NULL, ctx);
47  *   ctx->callback = callback;
48  *
49  *   ...
50  *
51  *   // Return async operation for upper layer
52  *   return op;
53  * }
54  *
55  * // This callback is called when silc_async_abort is called by upper layer.
56  * // The callback given to async_call must not be called after this.
57  * void async_call_abort(SilcAsyncOperation op, void *context)
58  * {
59  *   OpContext ctx = context;
60  *   ctx->aborted = TRUE;
61  *   ctx->callback = NULL;
62  * }
63  *
64  ***/
65
66 #ifndef SILCASYNC_H
67 #define SILCASYNC_H
68
69 /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperation
70  *
71  * NAME
72  *
73  *    typedef struct SilcAsyncOperationObject *SilcAsyncOperation;
74  *
75  * DESCRIPTION
76  *
77  *    The asynchronous operation context allocated by silc_async_alloc.
78  *    The layer that implements the asynchronous operation allocates this
79  *    context.  The layer that receives this context can use it to control
80  *    the underlaying asynchronous operation.  It is also possible to use
81  *    a pre-allocated context by using SilcAsyncOperationStruct instead
82  *    SilcAsyncOperation.
83  *
84  ***/
85 typedef struct SilcAsyncOperationObject *SilcAsyncOperation;
86
87 /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationStruct
88  *
89  * NAME
90  *
91  *    typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct;
92  *
93  * DESCRIPTION
94  *
95  *    The asynchronous operation context that can be used as a pre-allocated
96  *    context.  This is initialized with silc_async_init.  It need not
97  *    be uninitialized.  The layer that implements the asynchronous
98  *    operation initializes this context.  The layer that has access to this
99  *    context can use it to control the underlaying asynchronous operation.
100  *
101  ***/
102 typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct;
103
104 /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationAbort
105  *
106  * SYNOPSIS
107  *
108  *    typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op,
109  *                                            void *context);
110  *
111  * DESCRIPTION
112  *
113  *    This callback is called when upper layer calls the silc_async_abort,
114  *    and is used to actually perform the abortion of the asynchronous
115  *    operation.  The silc_async_free must not be called in this function.
116  *
117  *    This callback type can also be provided to silc_async_abort function
118  *    by the upper layer, if it wants that callback is called to the upper
119  *    layer when aborting the operation.
120  *
121  ***/
122 typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op,
123                                         void *context);
124
125 /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationPause
126  *
127  * SYNOPSIS
128  *
129  *    typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op,
130  *                                                SilcBool pause_operation,
131  *                                                void *context);
132  *
133  * DESCRIPTION
134  *
135  *    This callback is used to halt an operation, if upper layer calls the
136  *    silc_async_halt function, or to resume an operation if upper layer
137  *    calls the silc_async_resume, after it has earlier halted the operation.
138  *    If this callback is implemented it is guaranteed that the asynchronous
139  *    operation is not progressed when it is halted.  If the `pause_operation'
140  *    is TRUE the operation is halted.  If it is FALSE, then the operation
141  *    resumes its execution.  This function returns TRUE if the operation
142  *    was (or is going to be) halted or resumed, and FALSE on error.
143  *
144  ***/
145 typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op,
146                                             SilcBool pause_operation,
147                                             void *context);
148
149 /* Upper layer functions for managing asynchronous operations.  Layer
150    that has received SilcAsyncOperation context can control the async
151    operation with these functions. */
152
153 /****f* silcutil/SilcAsyncOperationAPI/silc_async_halt
154  *
155  * SYNOPSIS
156  *
157  *    SilcBool silc_async_halt(SilcAsyncOperation op);
158  *
159  * DESCRIPTION
160  *
161  *    Halt the execution of the asynchronous operation.  If the operation
162  *    supports this feature, it is guaranteed that the operation is halted
163  *    and its execution is not progressed until the silc_async_resume function
164  *    is called.  The operation still can be aborted even if it is halted.
165  *    If this function is not supported, calling this has no effect and the
166  *    function returns FALSE.  This function is for the upper layer that
167  *    controls the asynchronous operation.
168  *
169  ***/
170 SilcBool silc_async_halt(SilcAsyncOperation op);
171
172 /****f* silcutil/SilcAsyncOperationAPI/silc_async_resume
173  *
174  * SYNOPSIS
175  *
176  *    SilcBool silc_async_resume(SilcAsyncOperation op);
177  *
178  * DESCRIPTION
179  *
180  *    Resume the execution of the asynchronous operation.  If the halting of
181  *    the operation was supported, then this function is used to resume the
182  *    execution of the operation after it was halted.  If this function is
183  *    not supported, calling this has no effect and the function returns
184  *    FALSE.  This function is for the upper layer that controls the
185  *    asynchronous operation.
186  *
187  ***/
188 SilcBool silc_async_resume(SilcAsyncOperation op);
189
190 /****f* silcutil/SilcAsyncOperationAPI/silc_async_abort
191  *
192  * SYNOPSIS
193  *
194  *    void silc_async_abort(SilcAsyncOperation op,
195  *                          SilcAsyncOperationAbort abort_cb, void *context);
196  *
197  * DESCRIPTION
198  *
199  *    This function is used by upper layer that received SilcAsyncOperation
200  *    context from an asynchronous function, to abort the asynchronous
201  *    operation.  The `op' becomes invalid after this function returns.
202  *    It is also guaranteed (assuming the use of this API is implemented
203  *    correctly) that some other completion callback is not called after
204  *    the operation was aborted.  However, if the caller wants to receive
205  *    a callback when aborting the caller may specify the `abort_cb' and
206  *    `context' which will be called after the operation is aborted, but
207  *    before the `op' becomes invalid.  The `abort_cb' is called immediately
208  *    inside this function.
209  *
210  ***/
211 void silc_async_abort(SilcAsyncOperation op,
212                       SilcAsyncOperationAbort abort_cb, void *context);
213
214 /* The operation layer functions.  The layer that performs the async
215    operation use these functions. */
216
217 /****f* silcutil/SilcAsyncOperationAPI/silc_async_alloc
218  *
219  * SYNOPSIS
220  *
221  *    SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb,
222  *                                        SilcAsyncOperationPause pause_cb,
223  *                                        void *context);
224  *
225  * DESCRIPTION
226  *
227  *    Start asynchronous operation, and assign `abort_cb' callback for it,
228  *    which can be used by some upper layer to abort the asynchronous
229  *    operation, by calling the silc_async_abort.  The layer which calls
230  *    this function must also call silc_async_free when the asynchronous
231  *    operation is successfully completed.  If it is aborted by upper layer
232  *    then silc_async_free must not be called, since it is called by the
233  *    silc_async_abort function.
234  *
235  *    If the `pause_cb' is provided then the upper layer may also halt and
236  *    then later resume the execution of the operation, by calling the
237  *    silc_async_halt and silc_async_resume respectively.  If `pause_cb' is
238  *    not provided then these functions has no effect for this operation.
239  *
240  * EXAMPLE
241  *
242  *    SilcAsyncOperation silc_async_call(Callback callback, void *cb_context)
243  *    {
244  *      SilcAsyncOperation op;
245  *      ...
246  *
247  *      // Allocate async operation so that caller can control us, like abort
248  *      op = silc_async_alloc(silc_async_call_abort, NULL, ctx);
249  *
250  *      // Start async operation in FSM
251  *      silc_fsm_init(&ctx->fsm, ctx, fsm_destructor, ctx, schedule);
252  *      silc_fsm_start(&ctx->fsm, first_state);
253  *      ...
254  *
255  *      // Return async operation for upper layer
256  *      return op;
257  *    }
258  *
259  ***/
260 SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb,
261                                     SilcAsyncOperationPause pause_cb,
262                                     void *context);
263
264 /****f* silcutil/SilcAsyncOperationAPI/silc_async_init
265  *
266  * SYNOPSIS
267  *
268  *    SilcBool silc_async_init(SilcAsyncOperation op,
269  *                             SilcAsyncOperationAbort abort_cb,
270  *                             SilcAsyncOperationPause pause_cb,
271  *                             void *context);
272  *
273  * DESCRIPTION
274  *
275  *    Initializes and starts a pre-allocated asynchronous operation context,
276  *    and assigns `abort_cb' callback for it, which can be used by some upper
277  *    layer to abort the asynchronous operation, by calling the
278  *    silc_async_abort.  Since this use pre-allocated context, the function
279  *    silc_async_free need not be called.  This function is equivalent
280  *    to silc_async_alloc except this does not allocate any memory.  The `op'
281  *    needs not be uninitialized.  This returns always TRUE.
282  *
283  *    If the `pause_cb' is provided then the upper layer may also halt and
284  *    then later resume the execution of the operation, by calling the
285  *    silc_async_halt and silc_async_resume respectively.  If `pause_cb' is
286  *    not provided then these functions has no effect for this operation.
287  *
288  ***/
289 SilcBool silc_async_init(SilcAsyncOperation op,
290                          SilcAsyncOperationAbort abort_cb,
291                          SilcAsyncOperationPause pause_cb,
292                          void *context);
293
294 /****f* silcutil/SilcAsyncOperationAPI/silc_async_free
295  *
296  * SYNOPSIS
297  *
298  *    void silc_async_free(SilcAsyncOperation op);
299  *
300  * DESCRIPTION
301  *
302  *    Stop the asynchronous operation.  If the asynchronous operation ended
303  *    normally (ie. it was not aborted) this function must be called by the
304  *    caller who called silc_async_alloc.  The `op' will become invalid after
305  *    this and the upper layer must not call silc_async_abort after this
306  *    function is called.  The layer that calls this, must call some other
307  *    completion callback to the upper layer, so that it knows that the
308  *    asynchronous operation is completed.
309  *
310  ***/
311 void silc_async_free(SilcAsyncOperation op);
312
313 /****f* silcutil/SilcAsyncOperationAPI/silc_async_get_context
314  *
315  * SYNOPSIS
316  *
317  *    void *silc_async_get_context(SilcAsyncOperation op);
318  *
319  * DESCRIPTION
320  *
321  *    Returns the context that was given to the silc_async_alloc or
322  *    silc_async_init.
323  *
324  ***/
325 void *silc_async_get_context(SilcAsyncOperation op);
326
327 #include "silcasync_i.h"
328
329 #endif /* SILCASYNC_H */