diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-12-08 01:13:45 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:47:11 -0500 |
commit | 111a920fdb92ccef32f89b2f992bdd3051e5ac54 (patch) | |
tree | 24adf02842938ad320ad682b133eb76bd1be5cd8 /source4/libcli/composite | |
parent | 344703bfc0580419666e14217e6acf9e5f0c86c7 (diff) | |
download | samba-111a920fdb92ccef32f89b2f992bdd3051e5ac54.tar.gz samba-111a920fdb92ccef32f89b2f992bdd3051e5ac54.tar.xz samba-111a920fdb92ccef32f89b2f992bdd3051e5ac54.zip |
r12116: got rid of composite_trigger_done() and composite_trigger_error(), and
instead make the normal composite_done() and composite_error()
functions automatically trigger a delayed callback if the caller has
had no opportunity to setup a async callback
this removes one of the common mistakes in writing a composite function
(This used to be commit f9413ce792ded682e05134b66d433eeec293e6f1)
Diffstat (limited to 'source4/libcli/composite')
-rw-r--r-- | source4/libcli/composite/composite.c | 65 | ||||
-rw-r--r-- | source4/libcli/composite/composite.h | 2 |
2 files changed, 33 insertions, 34 deletions
diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c index 3842ddfe9fb..c9cc20e9235 100644 --- a/source4/libcli/composite/composite.c +++ b/source4/libcli/composite/composite.c @@ -35,6 +35,8 @@ NTSTATUS composite_wait(struct composite_context *c) { if (c == NULL) return NT_STATUS_NO_MEMORY; + c->used_wait = True; + while (c->state < COMPOSITE_STATE_DONE) { if (event_loop_once(c->event_ctx) != 0) { return NT_STATUS_UNSUCCESSFUL; @@ -45,44 +47,10 @@ NTSTATUS composite_wait(struct composite_context *c) } -/* - callback from composite_trigger_done() and composite_trigger_error() -*/ -static void composite_trigger(struct event_context *ev, struct timed_event *te, - struct timeval t, void *ptr) -{ - struct composite_context *c = talloc_get_type(ptr, struct composite_context); - if (c->async.fn) { - c->async.fn(c); - } -} - - -/* - trigger an immediate 'done' event on a composite context - this is used when the composite code works out that the call - can be completed without waiting for any external event -*/ -void composite_trigger_done(struct composite_context *c) -{ - c->state = COMPOSITE_STATE_DONE; - /* a zero timeout means immediate */ - event_add_timed(c->event_ctx, c, timeval_zero(), composite_trigger, c); -} - -void composite_trigger_error(struct composite_context *c) -{ - c->state = COMPOSITE_STATE_ERROR; - /* a zero timeout means immediate */ - event_add_timed(c->event_ctx, c, timeval_zero(), composite_trigger, c); -} - - /* * Some composite helpers that are handy if you write larger composite * functions. */ - BOOL composite_is_ok(struct composite_context *ctx) { if (NT_STATUS_IS_OK(ctx->status)) { @@ -95,8 +63,34 @@ BOOL composite_is_ok(struct composite_context *ctx) return False; } +/* + callback from composite_done() and composite_error() + + this is used to allow for a composite function to complete without + going through any state transitions. When that happens the caller + has had no opportunity to fill in the async callback fields + (ctx->async.fn and ctx->async.private) which means the usual way of + dealing with composite functions doesn't work. To cope with this, + we trigger a timer event that will happen then the event loop is + re-entered. This gives the caller a chance to setup the callback, + and allows the caller to ignore the fact that the composite + function completed early +*/ +static void composite_trigger(struct event_context *ev, struct timed_event *te, + struct timeval t, void *ptr) +{ + struct composite_context *c = talloc_get_type(ptr, struct composite_context); + if (c->async.fn) { + c->async.fn(c); + } +} + + void composite_error(struct composite_context *ctx, NTSTATUS status) { + if (!ctx->used_wait && !ctx->async.fn) { + event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx); + } ctx->status = status; SMB_ASSERT(!composite_is_ok(ctx)); } @@ -112,6 +106,9 @@ BOOL composite_nomem(const void *p, struct composite_context *ctx) void composite_done(struct composite_context *ctx) { + if (!ctx->used_wait && !ctx->async.fn) { + event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx); + } ctx->state = COMPOSITE_STATE_DONE; if (ctx->async.fn != NULL) { ctx->async.fn(ctx); diff --git a/source4/libcli/composite/composite.h b/source4/libcli/composite/composite.h index 1e6e9f5dc85..26490f1c4a2 100644 --- a/source4/libcli/composite/composite.h +++ b/source4/libcli/composite/composite.h @@ -57,4 +57,6 @@ struct composite_context { void (*fn)(struct composite_context *); void *private_data; } async; + + BOOL used_wait; }; |