1 /* 2 3 silcasync.h 4 5 Author: Pekka Riikonen <priikone@silcnet.org> 6 7 Copyright (C) 2005 - 2007 Pekka Riikonen 8 9 The contents of this file are subject to one of the Licenses specified 10 in the COPYING file; You may not use this file except in compliance 11 with the License. 12 13 The software distributed under the License is distributed on an "AS IS" 14 basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY 15 KIND, either expressed or implied. See the COPYING file for more 16 information. 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 */ 304