asynchronous programming with futures and await

29
Artur Laksberg Microsoft May 8th, 2014 Asynchronous programming with futures and await

Upload: xandy

Post on 23-Feb-2016

60 views

Category:

Documents


0 download

DESCRIPTION

Asynchronous programming with futures and await. Artur Laksberg Microsoft May 8th, 2014. Agenda. Asynchrony with callbacks Futures and Continuations Composition with futures await. Hollywood Principle. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Asynchronous programming with futures and await

Artur LaksbergMicrosoft May 8th, 2014

Asynchronous programming with futures and await

Page 2: Asynchronous programming with futures and await

Agenda• Asynchrony with callbacks• Futures and Continuations• Composition with futures• await

Page 3: Asynchronous programming with futures and await

Hollywood Principle

Don’t call us, we’ll call you!3

Page 4: Asynchronous programming with futures and await

Read From FIle: Naïve SolutionReturn a string, block on call:string read_string_from_file(string file);

string s = read_string_from_file("myfile.txt");cout << s;

Problem: blocking call

Page 5: Asynchronous programming with futures and await

Read From FIle: Callback SolutionDoes not return a string, takes a callback that accepts a string:template<typename Func>void read_string_from_file(string file, Func&& func);

...read_string_from_file("myfile.txt", [](string s) { cout << s;});

Page 6: Asynchronous programming with futures and await

Concatenate Files: Naive SolutionRead from one file, then read from another:template<typename Func>void concatenate_files(string file1, string file2, Func&& func){ read_string_from_file(file1, [func](string str1) { read_string_from_file(file2, [func](string str2) { func(str1 + str2); }); });}

Page 7: Asynchronous programming with futures and await

Concatenate Files: A “Better” Solutiontemplate<typename Func>void concatenate_files(string file1, string file2, Func&& func) {

auto results = make_shared<result_holder>();

read_string_from_file(file1, [=](string str) { if (results->str) { func(str + *results->str); } else{ results->str = make_unique<string>(str); } });

read_string_from_file(file2, [=](string str) { if (results->str) { func(*results->str + str); } else{ results->str = make_unique<string>(str); } });}

struct result_holder{ unique_ptr<string> str;};

? Spot the defect!

Page 8: Asynchronous programming with futures and await

std::future<T>std::shared_future<T>

Page 9: Asynchronous programming with futures and await

Long-Running WorkCounting lines in a file// Launch a task:future<int> work = async([] { return CountLinesInFile(…); });

// Collect the results:cout << work.get();

Problem: blocking call

Page 10: Asynchronous programming with futures and await

Proposal: Continuation(shared_)future::then

// Launch a task:future<int> work = CountLinesInFileAsync(...);

work.then([] (future<int> f) { // Get the result cout << f.get();});

Page 11: Asynchronous programming with futures and await

Binding Multiple Continuationsfuture<T1> t = async([](){ return func1();}).then ([](future<T1> n){ return func2(n.get());}).then ([](future<T2> n){ return func3(n.get());}).then ...

Page 12: Asynchronous programming with futures and await

Advanced CompositionSequential Composition:

Parallel Composition (only shared_future):f.then(A).then(B);

f.then(A);f.then(B);

Join and Choice (more on next page):auto f = when_all(a, b);auto f = when_any(a, b);

Page 13: Asynchronous programming with futures and await

JoinCreate a future that completes when all arguments completevector<future<int>> futures = get_futures();auto futureResult = when_all (begin(futures), end(futures)) .then([](future<vector<future<string>>> results) { for (auto& s : results.get() ) // will not block { cout << s.get(); // will not block } });

Page 14: Asynchronous programming with futures and await

JoinNow with heterogeneous argumentsfuture<int> future1 = ...;future<string> future2 = ...;auto futureResult = when_all(future1, future2) .then([](future<tuple<future<int>, future<string>>> results) { auto pair = results.get(); // will not block ... }});

Page 15: Asynchronous programming with futures and await

Concatenate Files: The Right SolutionTerse, efficient and safefuture<string> concatenate_files(string file1, string file2){ auto strings = when_all(read_string_from_file(file1), read_string_from_file(file2));

return strings.then([]( future<tuple<future<string>, future<string>>> strings) { auto pair = strings.get(); return pair.get<0>.get() + pair.get<1>.get(); });}

Page 16: Asynchronous programming with futures and await

Concatenate Files: The Right SolutionTerse, efficient and safe (with polymorphic lambdas)future<string> concatenate_files(string file1, string file2){ auto strings = when_all(read_string_from_file(file1), read_string_from_file(file2));

return strings.then([]( auto strings) { auto pair = strings.get(); return pair.get<0>.get() + pair.get<1>.get(); });}

Page 17: Asynchronous programming with futures and await

ChoiceCreate a future that completes when at least one of arguments completes:vector<future<int>> futures = get_futures();auto futureResult = when_any (begin(futures), end(futures)) .then([](future<vector<future<string>>> results) { for (auto& s : results.get() ) // will not block { if(s.ready()) cout << s.get(); // will not block } });

Page 18: Asynchronous programming with futures and await

make_ready_futurefuture<int> compute(int x) { if (x < 0) return make_ready_future<int>(-1); if (x == 0) return make_ready_future<int>(0); future<int> f1 = async([]() { return do_work(x); }); return f1;}

Page 19: Asynchronous programming with futures and await

is_readyfuture<int> f1 = async([]() { return possibly_long_computation(); });if(!f1.is_ready()) { //if not ready, attach a continuation and avoid a blocking wait fl.then([] (future<int> f2) { int v = f2.get(); process_value(v); });}// if ready, no need to add continuation, process value right away else { int v = f1.get(); process_value(v);}

Page 20: Asynchronous programming with futures and await

awaitand resumable functions

Page 21: Asynchronous programming with futures and await

Branches and loops

22

.get .thenstring read(string file){ istream fi = open(file).get(); string ret, chunk; while ((chunk = fi.read().get()).size()) ret += chunk; return ret;}

future<string> read(string file) { return open(file) .then([=](istream fi) { string ret, chunk; while (

???

Page 22: Asynchronous programming with futures and await

Branches and loops

23

.get .thenstring read(string file){ istream fi = open(file).get(); string ret, chunk; while ((chunk = fi.read().get()).size()) ret += chunk; return ret;}

future<string> read(string file){ return open(file) .then([=](istream fi) { auto ret = make_shared<string>(); auto next = make_shared<function<future<string>()>>( [=] { fi.read() .then([=](string chunk) { if (chunk.size()) { *ret += chunk; return next(); } return make_ready_future(*ret); }); }); return (*next)(); });}

Page 23: Asynchronous programming with futures and await
Page 24: Asynchronous programming with futures and await

Await ExampleGet a value, convert to string:

future<string> f() resumable{ future<int> f1 = async([]() { return possibly_long_computation(); });

int n = await f1; return to_string(n);}

Page 25: Asynchronous programming with futures and await

Branches and loops, with await

26

.get awaitstring read(string file){ istream fi = open(file).get(); string ret, chunk; while ((chunk = fi.read().get()).size()) ret += chunk; return ret;}

String read(string file){ istream fi = await open(file); string ret, chunk; while ((chunk = (await fi.read()).size()) ret += chunk; return ret;}

Page 26: Asynchronous programming with futures and await

Thread #2Thread #1

Resumable Side Stack Simulation

27

Main Stack

………

……

foo();t = async_bar()

Side Stackasync_bar();

do_work();………

await async_work();

somefunc();bool b = t.get()

<blocked>

More sync calls…

return true;

<completed>

Side Stackasync_work();

do_work();await create_task();

Longrunning is done!<suspended

>return task<void>

<suspended>return task<bool>

return;

<completed>

void foo() { task<bool> t = async_bar();

somefunc();

bool b = t.get();}

task<bool> async_bar() resumable { do_work(); ... // sync calls

await async_work();

// More sync calls ... return true;}

task<void> async_work() resumable { do_work();

await create_task( [] { longrunning (); });

return;}

done!async_work

is done!

Page 27: Asynchronous programming with futures and await

References• N3857: Improvements to std::future<T> and

Related APIs• N3858: Resumable Functions• N3970: Working Draft, Information technology –

Programming languages, their environments and system software interfaces – C++ Extensions for Concurrency

Page 28: Asynchronous programming with futures and await

“Concurrent programs wait faster”

Tony Hoare

Page 29: Asynchronous programming with futures and await