summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-08-15 09:46:23 +0200
committerStefan Metzmacher <metze@samba.org>2009-08-17 09:25:44 +0200
commit45e4be0d96abdc729252df1e97bb9a56302e5a4a (patch)
treea9bcfc8d68dee0b58d6534029c9012733b588484
parent26e114b83ce1de7515bfbf365da03ec3f18c95fd (diff)
downloadsamba-45e4be0d96abdc729252df1e97bb9a56302e5a4a.tar.gz
samba-45e4be0d96abdc729252df1e97bb9a56302e5a4a.tar.bz2
samba-45e4be0d96abdc729252df1e97bb9a56302e5a4a.zip
tevent: add tevent_req_cancel() infrastructure
This offers a generic way for callers to cancel an async request. metze
-rw-r--r--lib/tevent/tevent.h8
-rw-r--r--lib/tevent/tevent_internal.h19
-rw-r--r--lib/tevent/tevent_req.c43
3 files changed, 70 insertions, 0 deletions
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 56ae0ee082..d3556053ac 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -238,6 +238,14 @@ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx);
char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req);
+typedef bool (*tevent_req_cancel_fn)(struct tevent_req *);
+
+void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn);
+
+bool _tevent_req_cancel(struct tevent_req *req, const char *location);
+#define tevent_req_cancel(req) \
+ _tevent_req_cancel(req, __location__)
+
struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
void *pstate,
size_t state_size,
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index e260524208..513ca1c732 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -65,6 +65,15 @@ struct tevent_req {
tevent_req_print_fn private_print;
/**
+ * @brief A function to cancel the request
+ *
+ * The implementation might want to set a function
+ * that is called when the tevent_req_cancel() function
+ * was called.
+ */
+ tevent_req_cancel_fn private_cancel;
+
+ /**
* @brief Internal state of the request
*
* Callers should only access this via functions and never directly.
@@ -100,6 +109,16 @@ struct tevent_req {
const char *finish_location;
/**
+ * @brief The location where the request was canceled
+ *
+ * This uses the __location__ macro via the
+ * tevent_req_cancel() macro.
+ *
+ * This for debugging only.
+ */
+ const char *cancel_location;
+
+ /**
* @brief The external state - will be queried by the caller
*
* While the async request is being processed, state will remain in
diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index c6b11601dc..345a2fdcd1 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -398,3 +398,46 @@ void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn)
{
req->private_print = fn;
}
+
+/**
+ * @brief This function sets a cancel function for the given request
+ * @param[in] req The given request
+ * @param[in] fn A pointer to the cancel function
+ *
+ * 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.
+ *
+ */
+void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn)
+{
+ req->private_cancel = fn;
+}
+
+/**
+ * @brief This function tries to cancel the given request
+ * @param[in] req The given request
+ * @param[in] location Automaticly filled with the __location__ macro
+ * via the tevent_req_cancel() macro. This is for debugging
+ * only!
+ * @retval This function returns true is the request is cancelable.
+ * Otherwise false is returned.
+ *
+ * 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().
+ *
+ * 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, const char *location)
+{
+ if (req->private_cancel == NULL) {
+ return false;
+ }
+
+ return req->private_cancel(req);
+}