From ed78582847d3932763ad9b7b239f843306fa6fe9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 26 Sep 2018 21:19:34 +0200 Subject: [PATCH] sinkToSource(): Start the coroutine lazily In particular this causes copyStorePath() from HttpBinaryCacheStore to only start a download if needed. E.g. if the destination LocalStore goes to sleep waiting for the path lock and another process creates the path, then LocalStore::addToStore() will never read from the source so we don't have to do the download. --- src/libutil/serialise.cc | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 31df6fdfd..0e75eeec2 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -169,17 +169,13 @@ std::unique_ptr sinkToSource( { typedef boost::coroutines2::coroutine coro_t; + std::function fun; std::function eof; - coro_t::pull_type coro; + std::experimental::optional coro; + bool started = false; SinkToSource(std::function fun, std::function eof) - : eof(eof) - , coro([&](coro_t::push_type & yield) { - LambdaSink sink([&](const unsigned char * data, size_t len) { - if (len) yield(std::string((const char *) data, len)); - }); - fun(sink); - }) + : fun(fun), eof(eof) { } @@ -188,11 +184,19 @@ std::unique_ptr sinkToSource( size_t read(unsigned char * data, size_t len) override { - if (!coro) { eof(); abort(); } + if (!coro) + coro = coro_t::pull_type([&](coro_t::push_type & yield) { + LambdaSink sink([&](const unsigned char * data, size_t len) { + if (len) yield(std::string((const char *) data, len)); + }); + fun(sink); + }); + + if (!*coro) { eof(); abort(); } if (pos == cur.size()) { - if (!cur.empty()) coro(); - cur = coro.get(); + if (!cur.empty()) (*coro)(); + cur = coro->get(); pos = 0; }