diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/uv_link_observer_t.c | 33 | ||||
-rw-r--r-- | src/uv_link_t.c | 49 |
2 files changed, 36 insertions, 46 deletions
diff --git a/src/uv_link_observer_t.c b/src/uv_link_observer_t.c index 5479f67..dbd42ba 100644 --- a/src/uv_link_observer_t.c +++ b/src/uv_link_observer_t.c @@ -9,7 +9,7 @@ static int uv_link_observer_read_start(uv_link_t* link) { observer = container_of(link, uv_link_observer_t, link); - return uv_link_read_start(observer->target); + return uv_link_read_start(observer->link.parent); } @@ -18,7 +18,7 @@ static int uv_link_observer_read_stop(uv_link_t* link) { observer = container_of(link, uv_link_observer_t, link); - return uv_link_read_stop(observer->target); + return uv_link_read_stop(observer->link.parent); } @@ -33,7 +33,7 @@ static int uv_link_observer_write(uv_link_t* link, observer = container_of(link, uv_link_observer_t, link); - return uv_link_propagate_write(observer->target, source, bufs, nbufs, + return uv_link_propagate_write(observer->link.parent, source, bufs, nbufs, send_handle, cb, arg); } @@ -45,7 +45,7 @@ static int uv_link_observer_try_write(uv_link_t* link, observer = container_of(link, uv_link_observer_t, link); - return uv_link_try_write(observer->target, bufs, nbufs); + return uv_link_try_write(observer->link.parent, bufs, nbufs); } @@ -57,7 +57,7 @@ static int uv_link_observer_shutdown(uv_link_t* link, observer = container_of(link, uv_link_observer_t, link); - return uv_link_propagate_shutdown(observer->target, source, cb, arg); + return uv_link_propagate_shutdown(observer->link.parent, source, cb, arg); } @@ -84,12 +84,7 @@ 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; + cb(source); } @@ -106,13 +101,7 @@ static uv_link_methods_t uv_link_observer_methods = { }; -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 uv_link_observer_init(uv_link_observer_t* observer) { int err; memset(observer, 0, sizeof(*observer)); @@ -121,13 +110,5 @@ int uv_link_observer_init(uv_link_observer_t* observer, if (err != 0) return err; - observer->target = target; - - err = uv_link_chain(target, &observer->link); - if (err != 0) { - uv_link_close(&observer->link, uv_link_observer_empty_close_cb); - return err; - } - return 0; } diff --git a/src/uv_link_t.c b/src/uv_link_t.c index e930a8f..d63a07b 100644 --- a/src/uv_link_t.c +++ b/src/uv_link_t.c @@ -35,38 +35,47 @@ int uv_link_init(uv_link_t* link, uv_link_methods_t const* methods) { } -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; +static void uv_link_close_join(uv_link_t* link) { + if (--link->close_waiting == 0) + return link->saved_close_cb(link); +} - memset(link, 0, sizeof(*link)); - if (target == NULL) - cb(source); - else - uv_link_propagate_close(target, source, cb); +void uv_link_close(uv_link_t* link, uv_link_close_cb cb) { + uv_link_propagate_close(link, link, cb); } void uv_link_propagate_close(uv_link_t* link, uv_link_t* source, uv_link_close_cb cb) { + uv_link_t* root; + int count; + CHECK_EQ(link->child, NULL, "uv_link_t: attempt to close chained link"); - uv_link_methods_t const* methods; - methods = link->methods; + /* Find root */ + count = 1; + for (root = link; root->parent != NULL; root = root->parent) + count++; + + /* NOTE: This is very important line. Only because we `+=` here the + * recursive propagation is possible + */ + source->close_waiting += count; + + source->saved_close_cb = cb; - if (link->parent != NULL) - CHECK_EQ(uv_link_unchain(link->parent, link), 0, "uv_link_unchain()"); + /* Go from the root to the leaf, disconnecting and closing everything */ + while (root != NULL) { + uv_link_t* child; - link->saved_close_source = source; - link->saved_close_cb = cb; + child = root->child; + if (child != NULL) + CHECK_EQ(uv_link_unchain(root, child), 0, "close unchain"); - methods->close(link, link, uv_link_close_parent); + root->methods->close(root, source, uv_link_close_join); + root = child; + } } |