/* silcasync.h Author: Pekka Riikonen Copyright (C) 2005 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ /****h* silcutil/SILC Async Operation Interface * * DESCRIPTION * * SILC Async Operation API is an interface that can be used to control * asynchronous operations. All functions that take callback as argument * should return SilcAsyncOperation context. That context then can be * used to control, such as, abort the asynchronous operation. Using * SILC Async Operation API, asynchronous functions can be controlled * and aborted safely. * * The SILC Async Operation API is divided in two levels; the underlaying * operation level that implements the asynchronous operation, and the * upper layer that can control the asynchronous operation. The operation * layer must guarantee that if the upper layer aborts the asynchronous * operation, no callback function will be called back to the upper layer. * This must be remembered when implementing the operation layer. * * EXAMPLE * * SilcAsyncOperation async_call(Callback callback, void *cb_context) * { * SilcAsyncOperation op; * OpContext ctx; * * // Allocate async operation so that caller can control us, like abort * op = silc_async_alloc(async_call_abort, NULL, ctx); * ctx->callback = callback; * * ... * * // Return async operation for upper layer * return op; * } * * // This callback is called when silc_async_abort is called by upper layer. * // The callback given to async_call must not be called after this. * void async_call_abort(SilcAsyncOperation op, void *context) * { * OpContext ctx = context; * ctx->aborted = TRUE; * ctx->callback = NULL; * } * ***/ #ifndef SILCASYNC_H #define SILCASYNC_H /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperation * * NAME * * typedef struct SilcAsyncOperationObject *SilcAsyncOperation; * * DESCRIPTION * * The asynchronous operation context allocated by silc_async_alloc. * The layer that implements the asynchronous operation allocates this * context. The layer that receives this context can use it to control * the underlaying asynchronous operation. It is also possible to use * a pre-allocated context by using SilcAsyncOperationStruct instead * SilcAsyncOperation. * ***/ typedef struct SilcAsyncOperationObject *SilcAsyncOperation; /****s* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationStruct * * NAME * * typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct; * * DESCRIPTION * * The asynchronous operation context that can be used as a pre-allocated * context. This is initialized with silc_async_init. It need not * be uninitialized. The layer that implements the asynchronous * operation initializes this context. The layer that has access to this * context can use it to control the underlaying asynchronous operation. * ***/ typedef struct SilcAsyncOperationObject SilcAsyncOperationStruct; /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationAbort * * SYNOPSIS * * typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op, * void *context); * * DESCRIPTION * * This callback is called when upper layer calls the silc_async_abort, * and is used to actually perform the abortion of the asynchronous * operation. The silc_async_free must not be called in this function. * * This callback type can also be provided to silc_async_abort function * by the upper layer, if it wants that callback is called to the upper * layer when aborting the operation. * ***/ typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op, void *context); /****f* silcutil/SilcAsyncOperationAPI/SilcAsyncOperationPause * * SYNOPSIS * * typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op, * SilcBool pause_operation, * void *context); * * DESCRIPTION * * This callback is used to halt an operation, if upper layer calls the * silc_async_halt function, or to resume an operation if upper layer * calls the silc_async_resume, after it has earlier halted the operation. * If this callback is implemented it is guaranteed that the asynchronous * operation is not progressed when it is halted. If the `pause_operation' * is TRUE the operation is halted. If it is FALSE, then the operation * resumes its execution. This function returns TRUE if the operation * was (or is going to be) halted or resumed, and FALSE on error. * ***/ typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op, SilcBool pause_operation, void *context); /* Upper layer functions for managing asynchronous operations. Layer that has received SilcAsyncOperation context can control the async operation with these functions. */ /****f* silcutil/SilcAsyncOperationAPI/silc_async_halt * * SYNOPSIS * * SilcBool silc_async_halt(SilcAsyncOperation op); * * DESCRIPTION * * Halt the execution of the asynchronous operation. If the operation * supports this feature, it is guaranteed that the operation is halted * and its execution is not progressed until the silc_async_resume function * is called. The operation still can be aborted even if it is halted. * If this function is not supported, calling this has no effect and the * function returns FALSE. This function is for the upper layer that * controls the asynchronous operation. * ***/ SilcBool silc_async_halt(SilcAsyncOperation op); /****f* silcutil/SilcAsyncOperationAPI/silc_async_resume * * SYNOPSIS * * SilcBool silc_async_resume(SilcAsyncOperation op); * * DESCRIPTION * * Resume the execution of the asynchronous operation. If the halting of * the operation was supported, then this function is used to resume the * execution of the operation after it was halted. If this function is * not supported, calling this has no effect and the function returns * FALSE. This function is for the upper layer that controls the * asynchronous operation. * ***/ SilcBool silc_async_resume(SilcAsyncOperation op); /****f* silcutil/SilcAsyncOperationAPI/silc_async_abort * * SYNOPSIS * * void silc_async_abort(SilcAsyncOperation op, * SilcAsyncOperationAbort abort_cb, void *context); * * DESCRIPTION * * This function is used by upper layer that received SilcAsyncOperation * context from an asynchronous function, to abort the asynchronous * operation. The `op' becomes invalid after this function returns. * It is also guaranteed (assuming the use of this API is implemented * correctly) that some other completion callback is not called after * the operation was aborted. However, if the caller wants to receive * a callback when aborting the caller may specify the `abort_cb' and * `context' which will be called after the operation is aborted, but * before the `op' becomes invalid. The `abort_cb' is called immediately * inside this function. * ***/ void silc_async_abort(SilcAsyncOperation op, SilcAsyncOperationAbort abort_cb, void *context); /* The operation layer functions. The layer that performs the async operation use these functions. */ /****f* silcutil/SilcAsyncOperationAPI/silc_async_alloc * * SYNOPSIS * * SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb, * SilcAsyncOperationPause pause_cb, * void *context); * * DESCRIPTION * * Start asynchronous operation, and assign `abort_cb' callback for it, * which can be used by some upper layer to abort the asynchronous * operation, by calling the silc_async_abort. The layer which calls * this function must also call silc_async_free when the asynchronous * operation is successfully completed. If it is aborted by upper layer * then silc_async_free must not be called, since it is called by the * silc_async_abort function. * * If the `pause_cb' is provided then the upper layer may also halt and * then later resume the execution of the operation, by calling the * silc_async_halt and silc_async_resume respectively. If `pause_cb' is * not provided then these functions has no effect for this operation. * * EXAMPLE * * SilcAsyncOperation silc_async_call(Callback callback, void *cb_context) * { * SilcAsyncOperation op; * ... * * // Allocate async operation so that caller can control us, like abort * op = silc_async_alloc(silc_async_call_abort, NULL, ctx); * * // Start async operation in FSM * silc_fsm_init(&ctx->fsm, ctx, fsm_destructor, ctx, schedule); * silc_fsm_start(&ctx->fsm, first_state); * ... * * // Return async operation for upper layer * return op; * } * ***/ SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb, SilcAsyncOperationPause pause_cb, void *context); /****f* silcutil/SilcAsyncOperationAPI/silc_async_init * * SYNOPSIS * * SilcBool silc_async_init(SilcAsyncOperation op, * SilcAsyncOperationAbort abort_cb, * SilcAsyncOperationPause pause_cb, * void *context); * * DESCRIPTION * * Initializes and starts a pre-allocated asynchronous operation context, * and assigns `abort_cb' callback for it, which can be used by some upper * layer to abort the asynchronous operation, by calling the * silc_async_abort. Since this use pre-allocated context, the function * silc_async_free need not be called. This function is equivalent * to silc_async_alloc except this does not allocate any memory. The `op' * needs not be uninitialized. This returns always TRUE. * * If the `pause_cb' is provided then the upper layer may also halt and * then later resume the execution of the operation, by calling the * silc_async_halt and silc_async_resume respectively. If `pause_cb' is * not provided then these functions has no effect for this operation. * ***/ SilcBool silc_async_init(SilcAsyncOperation op, SilcAsyncOperationAbort abort_cb, SilcAsyncOperationPause pause_cb, void *context); /****f* silcutil/SilcAsyncOperationAPI/silc_async_free * * SYNOPSIS * * void silc_async_free(SilcAsyncOperation op); * * DESCRIPTION * * Stop the asynchronous operation. If the asynchronous operation ended * normally (ie. it was not aborted) this function must be called by the * caller who called silc_async_alloc. The `op' will become invalid after * this and the upper layer must not call silc_async_abort after this * function is called. The layer that calls this, must call some other * completion callback to the upper layer, so that it knows that the * asynchronous operation is completed. * ***/ void silc_async_free(SilcAsyncOperation op); /****f* silcutil/SilcAsyncOperationAPI/silc_async_get_context * * SYNOPSIS * * void *silc_async_get_context(SilcAsyncOperation op); * * DESCRIPTION * * Returns the context that was given to the silc_async_alloc or * silc_async_init. * ***/ void *silc_async_get_context(SilcAsyncOperation op); #include "silcasync_i.h" #endif /* SILCASYNC_H */