5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2005 - 2007 Pekka Riikonen
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.
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.
20 /****h* silcutil/SILC Async Operation Interface
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
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.
40 * SilcAsyncOperation async_call(Callback callback, void *cb_context)
42 * SilcAsyncOperation op;
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;
51 * // Return async operation for upper layer
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)
59 * OpContext ctx = context;
60 * ctx->aborted = TRUE;
61 * ctx->callback = NULL;
69 /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperation
73 * typedef struct SilcAsyncOperationObject *SilcAsyncOperation;
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
85 typedef struct SilcAsyncOperationObject *SilcAsyncOperation;
87 /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationStruct
91 * typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct;
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.
102 typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct;
104 /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationAbort
108 * typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op,
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.
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.
122 typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op,
125 /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationPause
129 * typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op,
130 * SilcBool pause_operation,
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.
145 typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op,
146 SilcBool pause_operation,
149 /* Upper layer functions for managing asynchronous operations. Layer
150 that has received SilcAsyncOperation context can control the async
151 operation with these functions. */
153 /****f* silcutil/SilcAsyncOperationAPI/silc_async_halt
157 * SilcBool silc_async_halt(SilcAsyncOperation op);
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.
170 SilcBool silc_async_halt(SilcAsyncOperation op);
172 /****f* silcutil/SilcAsyncOperationAPI/silc_async_resume
176 * SilcBool silc_async_resume(SilcAsyncOperation op);
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.
188 SilcBool silc_async_resume(SilcAsyncOperation op);
190 /****f* silcutil/SilcAsyncOperationAPI/silc_async_abort
194 * void silc_async_abort(SilcAsyncOperation op,
195 * SilcAsyncOperationAbort abort_cb, void *context);
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.
211 void silc_async_abort(SilcAsyncOperation op,
212 SilcAsyncOperationAbort abort_cb, void *context);
214 /* The operation layer functions. The layer that performs the async
215 operation use these functions. */
217 /****f* silcutil/SilcAsyncOperationAPI/silc_async_alloc
221 * SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb,
222 * SilcAsyncOperationPause pause_cb,
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.
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.
242 * SilcAsyncOperation silc_async_call(Callback callback, void *cb_context)
244 * SilcAsyncOperation op;
247 * // Allocate async operation so that caller can control us, like abort
248 * op = silc_async_alloc(silc_async_call_abort, NULL, ctx);
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);
255 * // Return async operation for upper layer
260 SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb,
261 SilcAsyncOperationPause pause_cb,
264 /****f* silcutil/SilcAsyncOperationAPI/silc_async_init
268 * SilcBool silc_async_init(SilcAsyncOperation op,
269 * SilcAsyncOperationAbort abort_cb,
270 * SilcAsyncOperationPause pause_cb,
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.
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.
289 SilcBool silc_async_init(SilcAsyncOperation op,
290 SilcAsyncOperationAbort abort_cb,
291 SilcAsyncOperationPause pause_cb,
294 /****f* silcutil/SilcAsyncOperationAPI/silc_async_free
298 * void silc_async_free(SilcAsyncOperation op);
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.
311 void silc_async_free(SilcAsyncOperation op);
313 /****f* silcutil/SilcAsyncOperationAPI/silc_async_get_context
317 * void *silc_async_get_context(SilcAsyncOperation op);
321 * Returns the context that was given to the silc_async_alloc or
325 void *silc_async_get_context(SilcAsyncOperation op);
327 #include "silcasync_i.h"
329 #endif /* SILCASYNC_H */