diff options
author | Fedor Indutny <fedor@indutny.com> | 2016-05-27 21:06:45 -0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2016-05-27 21:06:45 -0400 |
commit | 9f6eff69114a493047ffdf1bb6f0e3c86b2119aa (patch) | |
tree | 8f76debcc351a9e52ced96419d81a71afd64ecb5 /src | |
parent | ad8e9d158cc420f99c2b7c89567bed4870a88777 (diff) | |
download | uv_link_t-9f6eff69114a493047ffdf1bb6f0e3c86b2119aa.tar.gz |
include: close callbacks
Diffstat (limited to 'src')
-rw-r--r-- | src/uv_link_observer_t.c | 34 | ||||
-rw-r--r-- | src/uv_link_source_t.c | 33 | ||||
-rw-r--r-- | src/uv_link_t.c | 36 |
3 files changed, 75 insertions, 28 deletions
diff --git a/src/uv_link_observer_t.c b/src/uv_link_observer_t.c index e4deabb..5479f67 100644 --- a/src/uv_link_observer_t.c +++ b/src/uv_link_observer_t.c @@ -82,18 +82,35 @@ static void uv_link_observer_read_cb(uv_link_t* link, } +void uv_link_observer_close(uv_link_t* link, uv_link_t* source, + uv_link_close_cb cb) { + uv_link_observer_t* observer; + + observer = container_of(link, uv_link_observer_t, link); + + uv_link_propagate_close(observer->target, source, cb); + observer->target = NULL; +} + + static uv_link_methods_t uv_link_observer_methods = { .read_start = uv_link_observer_read_start, .read_stop = uv_link_observer_read_stop, .write = uv_link_observer_write, .try_write = uv_link_observer_try_write, .shutdown = uv_link_observer_shutdown, + .close = uv_link_observer_close, .alloc_cb_override = uv_link_observer_alloc_cb, .read_cb_override = uv_link_observer_read_cb }; +static void uv_link_observer_empty_close_cb(uv_link_t* link) { + /* no-op */ +} + + int uv_link_observer_init(uv_link_observer_t* observer, uv_link_t* target) { int err; @@ -108,24 +125,9 @@ int uv_link_observer_init(uv_link_observer_t* observer, err = uv_link_chain(target, &observer->link); if (err != 0) { - uv_link_close(&observer->link); + uv_link_close(&observer->link, uv_link_observer_empty_close_cb); return err; } return 0; } - - -int uv_link_observer_close(uv_link_observer_t* observer) { - int err; - - err = uv_link_unchain(observer->target, &observer->link); - if (err != 0) - return err; - - uv_link_close(&observer->link); - - observer->target = NULL; - - return 0; -} diff --git a/src/uv_link_source_t.c b/src/uv_link_source_t.c index c445fab..3d94ab9 100644 --- a/src/uv_link_source_t.c +++ b/src/uv_link_source_t.c @@ -137,12 +137,36 @@ static int uv_link_source_shutdown(uv_link_t* link, } +static void uv_link_source_close_cb(uv_handle_t* handle) { + uv_link_source_t* source; + + source = handle->data; + + source->stream = NULL; + source->close_cb(source->close_source); +} + + +static void uv_link_source_close(uv_link_t* link, uv_link_t* source, + uv_link_close_cb cb) { + uv_link_source_t* s; + + s = container_of(link, uv_link_source_t, link); + + s->close_cb = cb; + s->close_source = source; + + uv_close((uv_handle_t*) s->stream, uv_link_source_close_cb); +} + + static uv_link_methods_t uv_link_source_methods = { .read_start = uv_link_source_read_start, .read_stop = uv_link_source_read_stop, .write = uv_link_source_write, .try_write = uv_link_source_try_write, - .shutdown = uv_link_source_shutdown + .shutdown = uv_link_source_shutdown, + .close = uv_link_source_close }; @@ -161,10 +185,3 @@ int uv_link_source_init(uv_link_source_t* source, return 0; } - - -void uv_link_source_close(uv_link_source_t* source) { - uv_link_close(&source->link); - - source->stream = NULL; -} diff --git a/src/uv_link_t.c b/src/uv_link_t.c index 08b5064..e930a8f 100644 --- a/src/uv_link_t.c +++ b/src/uv_link_t.c @@ -35,10 +35,38 @@ int uv_link_init(uv_link_t* link, uv_link_methods_t const* methods) { } -void uv_link_close(uv_link_t* link) { - link->alloc_cb = NULL; - link->read_cb = NULL; - link->methods = NULL; +static void uv_link_close_parent(uv_link_t* link) { + uv_link_t* target; + uv_link_t* source; + uv_link_close_cb cb; + + target = link->parent; + source = link->saved_close_source; + cb = link->saved_close_cb; + + memset(link, 0, sizeof(*link)); + + if (target == NULL) + cb(source); + else + uv_link_propagate_close(target, source, cb); +} + + +void uv_link_propagate_close(uv_link_t* link, uv_link_t* source, + uv_link_close_cb cb) { + CHECK_EQ(link->child, NULL, "uv_link_t: attempt to close chained link"); + uv_link_methods_t const* methods; + + methods = link->methods; + + if (link->parent != NULL) + CHECK_EQ(uv_link_unchain(link->parent, link), 0, "uv_link_unchain()"); + + link->saved_close_source = source; + link->saved_close_cb = cb; + + methods->close(link, link, uv_link_close_parent); } |