Skip to content

Commit

Permalink
sinkToSource(): Start the coroutine lazily
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
edolstra committed Sep 26, 2018
1 parent 44e8630 commit ed78582
Showing 1 changed file with 15 additions and 11 deletions.
26 changes: 15 additions & 11 deletions src/libutil/serialise.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,13 @@ std::unique_ptr<Source> sinkToSource(
{
typedef boost::coroutines2::coroutine<std::string> coro_t;

std::function<void(Sink &)> fun;
std::function<void()> eof;
coro_t::pull_type coro;
std::experimental::optional<coro_t::pull_type> coro;
bool started = false;

SinkToSource(std::function<void(Sink &)> fun, std::function<void()> 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)
{
}

Expand All @@ -188,11 +184,19 @@ std::unique_ptr<Source> 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;
}

Expand Down

0 comments on commit ed78582

Please sign in to comment.