Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[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  ***/
39
40 #ifndef SILCASYNC_H
41 #define SILCASYNC_H
42
43 /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperation
44  *
45  * NAME
46  *
47  *    typedef struct SilcAsyncOperationObject *SilcAsyncOperation;
48  *
49  * DESCRIPTION
50  *
51  *    The asynchronous operation context allocated by silc_async_alloc.
52  *    The layer that implements the asynchronous operation allocates this
53  *    context.  The layer that receives this context can use it to control
54  *    the underlaying asynchronous operation.  It is also possible to use
55  *    a pre-allocated context by using SilcAsyncOperationStruct instead
56  *    SilcAsyncOperation.
57  *
58  ***/
59 typedef struct SilcAsyncOperationObject *SilcAsyncOperation;
60
61 /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationStruct
62  *
63  * NAME
64  *
65  *    typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct;
66  *
67  * DESCRIPTION
68  *
69  *    The asynchronous operation context that can be used as a pre-allocated
70  *    context.  This is initialized with silc_async_init.  It need not
71  *    be uninitialized.  The layer that implements the asynchronous
72  *    operation initializes this context.  The layer that has access to this
73  *    context can use it to control the underlaying asynchronous operation.
74  *
75  ***/
76 typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct;
77
78 /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationAbort
79  *
80  * SYNOPSIS
81  *
82  *    typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op,
83  *                                            void *context);
84  *
85  * DESCRIPTION
86  *
87  *    This callback is called when upper layer calls the silc_async_abort,
88  *    and is used to actually perform the abortion of the asynchronous
89  *    operation.  The silc_async_free must not be called in this function.
90  *
91  *    This callback type can also be provided to silc_async_abort function
92  *    by the upper layer, if it wants that callback is called to the upper
93  *    layer when aborting the operation.
94  *
95  ***/
96 typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op,
97                                         void *context);
98
99 /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationPause
100  *
101  * SYNOPSIS
102  *
103  *    typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op,
104  *                                                SilcBool pause_operation,
105  *                                                void *context);
106  *
107  * DESCRIPTION
108  *
109  *    This callback is used to halt an operation, if upper layer calls the
110  *    silc_async_halt function, or to resume an operation if upper layer
111  *    calls the silc_async_resume, after it has earlier halted the operation.
112  *    If this callback is implemented it is guaranteed that the asynchronous
113  *    operation is not progressed when it is halted.  If the `pause_operation'
114  *    is TRUE the operation is halted.  If it is FALSE, then the operation
115  *    resumes its execution.  This function returns TRUE if the operation
116  *    was (or is going to be) halted or resumed, and FALSE on error.
117  *
118  ***/
119 typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op,
120                                             SilcBool pause_operation,
121                                             void *context);
122
123 /* Upper layer functions for managing asynchronous operations.  Layer
124    that has received SilcAsyncOperation context can control the async
125    operation with these functions. */
126
127 /****f* silcutil/SilcAsyncOperationAPI/silc_async_halt
128  *
129  * SYNOPSIS
130  *
131  *    SilcBool silc_async_halt(SilcAsyncOperation op);
132  *
133  * DESCRIPTION
134  *
135  *    Halt the execution of the asynchronous operation.  If the operation
136  *    supports this feature, it is guaranteed that the operation is halted
137  *    and its execution is not progressed until the silc_async_resume function
138  *    is called.  The operation still can be aborted even if it is halted.
139  *    If this function is not supported, calling this has no effect and the
140  *    function returns FALSE.  This function is for the upper layer that
141  *    controls the asynchronous operation.
142  *
143  ***/
144 SilcBool silc_async_halt(SilcAsyncOperation op);
145
146 /****f* silcutil/SilcAsyncOperationAPI/silc_async_resume
147  *
148  * SYNOPSIS
149  *
150  *    SilcBool silc_async_resume(SilcAsyncOperation op);
151  *
152  * DESCRIPTION
153  *
154  *    Resume the execution of the asynchronous operation.  If the halting of
155  *    the operation was supported, then this function is used to resume the
156  *    execution of the operation after it was halted.  If this function is
157  *    not supported, calling this has no effect and the function returns
158  *    FALSE.  This function is for the upper layer that controls the
159  *    asynchronous operation.
160  *
161  ***/
162 SilcBool silc_async_resume(SilcAsyncOperation op);
163
164 /****f* silcutil/SilcAsyncOperationAPI/silc_async_abort
165  *
166  * SYNOPSIS
167  *
168  *    void silc_async_abort(SilcAsyncOperation op,
169  *                          SilcAsyncOperationAbort abort_cb, void *context);
170  *
171  * DESCRIPTION
172  *
173  *    This function is used by upper layer that received SilcAsyncOperation
174  *    context from an asynchronous function, to abort the asynchronous
175  *    operation.  The `op' becomes invalid after this function returns.
176  *    It is also guaranteed (assuming the use of this API is implemented
177  *    correctly) that some other completion callback is not called after
178  *    the operation was aborted.  However, if the caller wants to receive
179  *    a callback when aborting the caller may specify the `abort_cb' and
180  *    `context' which will be called after the operation is aborted, but
181  *    before the `op' becomes invalid.  The `abort_cb' is called immediately
182  *    inside this function.
183  *
184  ***/
185 void silc_async_abort(SilcAsyncOperation op,
186                       SilcAsyncOperationAbort abort_cb, void *context);
187
188 /* The operation layer functions.  The layer that performs the async
189    operation use these functions. */
190
191 /****f* silcutil/SilcAsyncOperationAPI/silc_async_alloc
192  *
193  * SYNOPSIS
194  *
195  *    SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb,
196  *                                        SilcAsyncOperationPause pause_cb,
197  *                                        void *context);
198  *
199  * DESCRIPTION
200  *
201  *    Start asynchronous operation, and assign `abort_cb' callback for it,
202  *    which can be used by some upper layer to abort the asynchronous
203  *    operation, by calling the silc_async_abort.  The layer which calls
204  *    this function must also call silc_async_free when the asynchronous
205  *    operation is successfully completed.  If it is aborted by upper layer
206  *    then silc_async_free must not be called, since it is called by the
207  *    silc_async_abort function.
208  *
209  *    If the `pause_cb' is provided then the upper layer may also halt and
210  *    then later resume the execution of the operation, by calling the
211  *    silc_async_halt and silc_async_resume respectively.  If `pause_cb' is
212  *    not provided then these functions has no effect for this operation.
213  *
214  * EXAMPLE
215  *
216  *    SilcAsyncOperation silc_async_call(Callback callback, void *cb_context)
217  *    {
218  *      SilcAsyncOperation op;
219  *      ...
220  *
221  *      // Allocate async operation so that caller can control us, like abort
222  *      op = silc_async_alloc(silc_async_call_abort, NULL, ctx);
223  *
224  *      // Start async operation in FSM
225  *      silc_fsm_init(&ctx->fsm, ctx, fsm_destructor, ctx, schedule);
226  *      silc_fsm_start(&ctx->fsm, first_state);
227  *      ...
228  *
229  *      // Return async operation for upper layer
230  *      return op;
231  *    }
232  *
233  ***/
234 SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb,
235                                     SilcAsyncOperationPause pause_cb,
236                                     void *context);
237
238 /****f* silcutil/SilcAsyncOperationAPI/silc_async_init
239  *
240  * SYNOPSIS
241  *
242  *    SilcBool silc_async_init(SilcAsyncOperation op,
243  *                             SilcAsyncOperationAbort abort_cb,
244  *                             SilcAsyncOperationPause pause_cb,
245  *                             void *context);
246  *
247  * DESCRIPTION
248  *
249  *    Initializes and starts a pre-allocated asynchronous operation context,
250  *    and assigns `abort_cb' callback for it, which can be used by some upper
251  *    layer to abort the asynchronous operation, by calling the
252  *    silc_async_abort.  Since this use pre-allocated context, the function
253  *    silc_async_free need not be called.  This function is equivalent
254  *    to silc_async_alloc except this does not allocate any memory.  The `op'
255  *    needs not be uninitialized.
256  *
257  *    If the `pause_cb' is provided then the upper layer may also halt and
258  *    then later resume the execution of the operation, by calling the
259  *    silc_async_halt and silc_async_resume respectively.  If `pause_cb' is
260  *    not provided then these functions has no effect for this operation.
261  *
262  ***/
263 SilcBool silc_async_init(SilcAsyncOperation op,
264                          SilcAsyncOperationAbort abort_cb,
265                          SilcAsyncOperationPause pause_cb,
266                          void *context);
267
268 /****f* silcutil/SilcAsyncOperationAPI/silc_async_free
269  *
270  * SYNOPSIS
271  *
272  *    void silc_async_free(SilcAsyncOperation op);
273  *
274  * DESCRIPTION
275  *
276  *    Stop the asynchronous operation.  If the asynchronous operation ended
277  *    normally (ie. it was not aborted) this function must be called by the
278  *    caller who called silc_async_alloc.  The `op' will become invalid after
279  *    this and the upper layer must not call silc_async_abort after this
280  *    function is called.  The layer that calls this, must call some other
281  *    completion callback to the upper layer, so that it knows that the
282  *    asynchronous operation is completed.
283  *
284  ***/
285 void silc_async_free(SilcAsyncOperation op);
286
287 /****f* silcutil/SilcAsyncOperationAPI/silc_async_get_context
288  *
289  * SYNOPSIS
290  *
291  *    void *silc_async_get_context(SilcAsyncOperation op);
292  *
293  * DESCRIPTION
294  *
295  *    Returns the context that was given to the silc_async_alloc or
296  *    silc_async_init.
297  *
298  ***/
299 void *silc_async_get_context(SilcAsyncOperation op);
300
301 #include "silcasync_i.h"
302
303 #endif /* SILCASYNC_H */