_tevent_req_cancel(req, __location__)
#endif
+/**
+ * @brief A typedef for a cleanup function for a tevent request.
+ *
+ * @param[in] req The tevent request calling this function.
+ *
+ * @param[in] req_state The current tevent_req_state.
+ *
+ */
+typedef void (*tevent_req_cleanup_fn)(struct tevent_req *req,
+ enum tevent_req_state req_state);
+
+/**
+ * @brief This function sets a cleanup function for the given tevent request.
+ *
+ * This function can be used to setup a cleanup function for the given request.
+ * This will be triggered when the tevent_req_done() or tevent_req_error()
+ * function was called, before notifying the callers callback function,
+ * and also before scheduling the deferred trigger.
+ *
+ * This might be useful if more than one tevent_req belong together
+ * and need to finish both requests at the same time.
+ *
+ * The cleanup function is able to call tevent_req_done() or tevent_req_error()
+ * recursively, the cleanup function is only triggered the first time.
+ *
+ * The cleanup function is also called by tevent_req_received()
+ * (possibly triggered from tevent_req_destructor()) before destroying
+ * the private data of the tevent_req.
+ *
+ * @param[in] req The request to use.
+ *
+ * @param[in] fn A pointer to the cancel function.
+ */
+void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn);
+
#ifdef DOXYGEN
/**
* @brief Create an async tevent request.
*/
tevent_req_cancel_fn private_cancel;
+ /**
+ * @brief A function to cleanup the request
+ *
+ * The implementation might want to set a function
+ * that is called before the tevent_req_done() and tevent_req_error()
+ * trigger the callers callback function.
+ */
+ struct {
+ tevent_req_cleanup_fn fn;
+ enum tevent_req_state state;
+ } private_cleanup;
+
/**
* @brief Internal state of the request
*
}
}
+static void tevent_req_cleanup(struct tevent_req *req)
+{
+ if (req->private_cleanup.fn == NULL) {
+ return;
+ }
+
+ if (req->private_cleanup.state >= req->internal.state) {
+ /*
+ * Don't call the cleanup_function multiple times for the same
+ * state recursively
+ */
+ return;
+ }
+
+ req->private_cleanup.state = req->internal.state;
+ req->private_cleanup.fn(req, req->internal.state);
+}
+
static void tevent_req_finish(struct tevent_req *req,
enum tevent_req_state state,
const char *location)
TALLOC_FREE(req->internal.timer);
req->internal.state = state;
+ req->internal.finish_location = location;
+
+ tevent_req_cleanup(req);
+
_tevent_req_notify_callback(req, location);
}
req->internal.state = TEVENT_REQ_RECEIVED;
+ tevent_req_cleanup(req);
+
TALLOC_FREE(req->data);
}
return req->private_cancel(req);
}
+
+void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn)
+{
+ req->private_cleanup.state = req->internal.state;
+ req->private_cleanup.fn = fn;
+}