diff options
Diffstat (limited to 'lib/tevent/tevent.h')
-rw-r--r-- | lib/tevent/tevent.h | 390 |
1 files changed, 375 insertions, 15 deletions
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index ad1f2c9cc3..edddcdf1d5 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -40,6 +40,16 @@ struct tevent_timer; struct tevent_immediate; struct tevent_signal; +/** + * @defgroup tevent The tevent API + * + * The tevent low-level API + * + * @todo description + * + * @{ + */ + /* event handler types */ typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, struct tevent_fd *fde, @@ -63,11 +73,86 @@ typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, void *siginfo, void *private_data); +/** + * @brief Create a event_context structure. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @return An allocated tevent context, NULL on error. + * + * @see tevent_context_init() + */ struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); + +/** + * @brief Create a event_context structure and name it. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @param[in] name The name for the tevent context. + * + * @return An allocated tevent context, NULL on error. + */ struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); + +/** + * @brief List available backends. + * + * @param[in] mem_ctx The memory context to use. + * + * @return A string vector with a terminating NULL element, NULL + * on error. + */ const char **tevent_backend_list(TALLOC_CTX *mem_ctx); + +/** + * @brief Set the default tevent backent. + * + * @param[in] backend The name of the backend to set. + */ void tevent_set_default_backend(const char *backend); +#if DOXYGEN +/** + * @brief Add a file descriptor based event. + * + * If flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when + * the returned fd_event context is freed. + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] fd The file descriptor to base the event on. + * + * @param[in] flags + * + * @param[in] handler The callback handler for the event. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @param[in] handler_name The name to identify the callback handler. + * + * @return The file descriptor based event, NULL on error. + * + * @todo Document flags + */ +struct tevent_fd *tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name); +#else struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, int fd, @@ -79,6 +164,7 @@ struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, #define tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ #handler, __location__) +#endif struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, TALLOC_CTX *mem_ctx, @@ -150,7 +236,9 @@ void tevent_set_abort_fn(void (*abort_fn)(const char *reason)); #define TEVENT_FD_NOT_READABLE(fde) \ tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) -/* DEBUG */ +/** + * Debug level of tevent + */ enum tevent_debug_level { TEVENT_DEBUG_FATAL, TEVENT_DEBUG_ERROR, @@ -167,6 +255,28 @@ int tevent_set_debug(struct tevent_context *ev, int tevent_set_debug_stderr(struct tevent_context *ev); /** + * @} + */ + +/** + * @defgroup tevent_request The tevent request functions. + * @ingroup tevent + * + * This represents an async request being processed by callbacks via an event + * context. A user can issue for example a write request to a socket, giving + * an implementation function the fd, the buffer and the number of bytes to + * transfer. The function issuing the request will immediately return without + * blocking most likely without having sent anything. The API user then fills + * in req->async.fn and req->async.private_data, functions that are called + * when the request is finished. + * + * It is up to the user of the async request to talloc_free it after it has + * finished. This can happen while the completion function is called. + * + * @{ + */ + +/** * An async request moves between the following 4 states: */ enum tevent_req_state { @@ -202,50 +312,132 @@ enum tevent_req_state { /** * @brief An async request - * - * This represents an async request being processed by callbacks via an event - * context. A user can issue for example a write request to a socket, giving - * an implementation function the fd, the buffer and the number of bytes to - * transfer. The function issuing the request will immediately return without - * blocking most likely without having sent anything. The API user then fills - * in req->async.fn and req->async.private_data, functions that are called - * when the request is finished. - * - * It is up to the user of the async request to talloc_free it after it has - * finished. This can happen while the completion function is called. */ - struct tevent_req; typedef void (*tevent_req_fn)(struct tevent_req *); void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); -void *_tevent_req_callback_data(struct tevent_req *req); -void *_tevent_req_data(struct tevent_req *req); +void *_tevent_req_callback_data(struct tevent_req *req); #define tevent_req_callback_data(_req, _type) \ talloc_get_type_abort(_tevent_req_callback_data(_req), _type) + #define tevent_req_callback_data_void(_req) \ _tevent_req_callback_data(_req) + +void *_tevent_req_data(struct tevent_req *req); #define tevent_req_data(_req, _type) \ talloc_get_type_abort(_tevent_req_data(_req), _type) typedef char *(*tevent_req_print_fn)(struct tevent_req *, TALLOC_CTX *); +/** + * @brief This function sets a print function for the given request. + * + * This function can be used to setup a print function for the given request. + * This will be triggered if the tevent_req_print() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the print function + * + * @note This function should only be used for debugging. + */ void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); +/** + * @brief The default print function for creating debug messages. + * + * The function should not be used by users of the async API, + * but custom print function can use it and append custom text + * to the string. + * + * @param[in] req The request to be printed. + * + * @param[in] mem_ctx The memory context for the result. + * + * @return Text representation of request. + * + */ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); +/** + * @brief Print an tevent_req structure in debug messages. + * + * This function should be used by callers of the async API. + * + * @param[in] mem_ctx The memory context for the result. + * + * @param[in] req The request to be printed. + * + * @return Text representation of request. + */ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); typedef bool (*tevent_req_cancel_fn)(struct tevent_req *); +/** + * @brief This function sets a cancel function for the given tevent request. + * + * This function can be used to setup a cancel function for the given request. + * This will be triggered if the tevent_req_cancel() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the cancel function. + */ void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); +#ifdef DOXYGEN +/** + * @brief Try to cancel the given tevent request. + * + * This function can be used to cancel the given request. + * + * It is only possible to cancel a request when the implementation + * has registered a cancel function via the tevent_req_set_cancel_fn(). + * + * @param[in] req The request to use. + * + * @return This function returns true is the request is cancelable, + * othererwise false is returned. + * + * @note Even if the function returns true, the caller need to wait + * for the function to complete normally. + * Only the _recv() function of the given request indicates + * if the request was really canceled. + */ +bool tevent_req_cancel(struct tevent_req *req); +#else bool _tevent_req_cancel(struct tevent_req *req, const char *location); #define tevent_req_cancel(req) \ _tevent_req_cancel(req, __location__) +#endif +#if DOXYGEN +/** + * @brief Create an async tevent request. + * + * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS. + * + * @param[in] mem_ctx The memory context for the result. + * + * @param[in] pstate The private state of the request. + * + * @param[in] state_size The size of the private state of the request. + * + * @param[in] type The name of the request. + * + * @return A new async request. NULL on error. + */ +struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx, + void *pstate, + size_t state_size, + const char *type); +#else struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, void *pstate, size_t state_size, @@ -255,6 +447,7 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, #define tevent_req_create(_mem_ctx, _pstate, _type) \ _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ #_type, __location__) +#endif bool tevent_req_set_endtime(struct tevent_req *req, struct tevent_context *ev, @@ -264,28 +457,152 @@ void _tevent_req_notify_callback(struct tevent_req *req, const char *location); #define tevent_req_notify_callback(req) \ _tevent_req_notify_callback(req, __location__) +#ifdef DOXYGEN +/** + * @brief An async request has successfully finished. + * + * This function is to be used by implementors of async requests. When a + * request is successfully finished, this function calls the user's completion + * function. + * + * @param[in] req The finished request. + */ +void tevent_req_done(struct tevent_req *req); +#else void _tevent_req_done(struct tevent_req *req, const char *location); #define tevent_req_done(req) \ _tevent_req_done(req, __location__) +#endif +#ifdef DOXYGEN +/** + * @brief An async request has seen an error. + * + * This function is to be used by implementors of async requests. When a + * request can not successfully completed, the implementation should call this + * function with the appropriate status code. + * + * If error is 0 the function returns false and does nothing more. + * + * @param[in] req The request with an error. + * + * @param[in] error The error code. + * + * @return On success true is returned, false if error is 0. + * + * @code + * int error = first_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * error = second_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * tevent_req_done(req); + * return; + * @endcode + */ +bool tevent_req_error(struct tevent_req *req, + uint64_t error); +#else bool _tevent_req_error(struct tevent_req *req, uint64_t error, const char *location); #define tevent_req_error(req, error) \ _tevent_req_error(req, error, __location__) +#endif +#ifdef DOXYGEN +/** + * @brief Helper function for nomem check. + * + * Convenience helper to easily check alloc failure within a callback + * implementing the next step of an async request. + * + * @param[in] p The pointer to be checked. + * + * @param[in] req The request being processed. + * + * @code + * p = talloc(mem_ctx, bla); + * if (tevent_req_nomem(p, req)) { + * return; + * } + * @endcode + */ +bool tevent_req_nomem(const void *p, + struct tevent_req *req); +#else bool _tevent_req_nomem(const void *p, struct tevent_req *req, const char *location); #define tevent_req_nomem(p, req) \ _tevent_req_nomem(p, req, __location__) +#endif +/** + * @brief Finish a request before the caller had the change to set the callback. + * + * An implementation of an async request might find that it can either finish + * the request without waiting for an external event, or it can't even start + * the engine. To present the illusion of a callback to the user of the API, + * the implementation can call this helper function which triggers an + * immediate timed event. This way the caller can use the same calling + * conventions, independent of whether the request was actually deferred. + * + * @param[in] req The finished request. + * + * @param[in] ev The tevent_context for the timed event. + * + * @return The given request will be returned. + */ struct tevent_req *tevent_req_post(struct tevent_req *req, struct tevent_context *ev); +/** + * @brief Check if the given request is still in progress. + * + * It is typically used by sync wrapper functions. + * + * This function destroys the attached private data. + * + * @param[in] req The request to poll. + * + * @return The boolean form of "is in progress". + */ bool tevent_req_is_in_progress(struct tevent_req *req); +/** + * @brief Actively poll for the given request to finish. + * + * This function is typically used by sync wrapper functions. + * + * @param[in] req The request to poll. + * + * @param[in] ev The tevent_context to be used. + * + * @return On success true is returned. If a critical error has + * happened in the tevent loop layer false is returned. + * This is not the return value of the given request! + * + * @note This should only be used if the given tevent context was created by the + * caller, to avoid event loop nesting. + * + * @code + * req = tstream_writev_queue_send(mem_ctx, + * ev_ctx, + * tstream, + * send_queue, + * iov, 2); + * ok = tevent_req_poll(req, tctx->ev); + * rc = tstream_writev_queue_recv(req, &sys_errno); + * TALLOC_FREE(req); + * @endcode + */ bool tevent_req_poll(struct tevent_req *req, struct tevent_context *ev); @@ -293,6 +610,13 @@ bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, uint64_t *error); +/** + * @brief Use as the last action of a _recv() function. + * + * This function destroys the attached private data. + * + * @param[in] req The finished request. + */ void tevent_req_received(struct tevent_req *req); struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, @@ -300,6 +624,17 @@ struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, struct timeval wakeup_time); bool tevent_wakeup_recv(struct tevent_req *req); +/* @} */ + +/** + * @defgroup tevent_helpers The tevent helper functiions + * @ingroup tevent + * + * @todo description + * + * @{ + */ + int tevent_timeval_compare(const struct timeval *tv1, const struct timeval *tv2); @@ -319,6 +654,16 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); +/* @} */ + + +/** + * @defgroup tevent_queue The tevent queue functions + * @ingroup tevent + * + * @{ + */ + struct tevent_queue; struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, @@ -368,11 +713,16 @@ int _tevent_loop_until(struct tevent_context *ev, int tevent_re_initialise(struct tevent_context *ev); +/* @} */ /** + * @defgroup tevent_ops The tevent operation functions + * @ingroup tevent + * * The following structure and registration functions are exclusively * needed for people writing and pluggin a different event engine. * There is nothing useful for normal tevent user in here. + * @{ */ struct tevent_ops { @@ -425,11 +775,19 @@ struct tevent_ops { bool tevent_register_backend(const char *name, const struct tevent_ops *ops); +/* @} */ /** + * @defgroup tevent_compat The tevent compatibility functions + * @ingroup tevent + * * The following definitions are usueful only for compatibility with the * implementation originally developed within the samba4 code and will be * soon removed. Please NEVER use in new code. + * + * @todo Ignore it? + * + * @{ */ #ifdef TEVENT_COMPAT_DEFINES @@ -506,4 +864,6 @@ bool tevent_register_backend(const char *name, const struct tevent_ops *ops); #endif /* TEVENT_COMPAT_DEFINES */ +/* @} */ + #endif /* __TEVENT_H__ */ |