+ All Categories
Home > Documents > Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move...

Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move...

Date post: 28-Mar-2015
Category:
Upload: cristobal-truman
View: 218 times
Download: 1 times
Share this document with a friend
Popular Tags:
26
Transcript
Page 1: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.
Page 2: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Bartosz Milewski

I see a monad in your future

Page 3: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

ConcurrencyFirst class functionsGeneric programmingMemory Management (move semantics)

Math nomenclatureFunctorApplicative FunctorMonadMonoid

Functional Patterns in C++

Page 4: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Sorting: compare functionFind, copy_if: predicate functionAccumulate: binary function

Higher Order Functions

for_each(v.begin(), v.end(), [](char c) { cout << c; });

transform(v.begin(), v.end(), w.begin(), [](int x) { return x * x; });

Page 5: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Currying, partial application: bindCombining algorithms

Combinators

v.erase(remove_if(v.begin(), v.end(), bind(logical_and<bool>(), bind(greater<int>(), _1, -10), bind(less<int>(), _1, 10))), v.end());

Page 6: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Channel for passing data (John Reppy, ML)PromiseFuture

Future

Page 7: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Page 7

Promise

promise<string> prms; Thread A Thread B

Promise

Sharedstate

Page 8: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Sharedstate

Page 8

Future

promise<string> prms;auto ftr = prms.get_future();

Thread A Thread B

Future

Promise

Page 9: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Page 9

Create thread

promise<string> prms;auto ftr = prms.get_future();thread th(&thFun, std::move(prms));

Thread A Thread B

Sharedstate

Future

Promise

Page 10: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Page 10set_value

promise<string> prms;auto ftr = prms.get_future();thread th(&thFun, std::move(prms));

Thread A Thread B

Sharedstate

Future

Promise

prms.set_value(“Hello from future”);

Hello

Thread B

Page 11: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Page 11get

promise<string> prms;auto ftr = prms.get_future();thread th(&thFun, std::move(prms));std::string str = ftr.get();

Thread A Thread B

Sharedstate

Future

Promise

prms.set_value(“Hello from future”);

Hello

Thread B

Page 12: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

ComposabilityOrthogonality (Separation of concerns)

Library Design

Page 13: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Problem: Apply a function to a future

future<string> ftr = async(…);…string s = ftr.get(); // blocks?… then continue to parse(s)

Then Pattern

Page 14: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

future<string> ftr = async(…);string s = ftr.get(); // blocks?… then parse(s)

Then Combinator

template<typename F> auto future::then(F&& func) -> future<decltype(func(*this))>;future<Tree> fTree = ftr.then([](future<string> fstr) { return parse(fstr.get()); // doesn’t block});Tree tree = fTree.get(); // blocks?

future<Tree> fTree = ftr.next(parse);Tree tree = fTree.get(); // blocks?

Next combinator

Page 15: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

next “lifts” parse to act on futures

Function Liftingfuture<string> fStr = …future<Tree> fTree = fStr.next(parse);

» transform “lifts” square to act on containers

vector<int> v = {1, 2, 3};vector<int> w;w.resize(v.size());transform(v.begin(), v.end(), w.begin(), square);

Page 16: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Unconstrained parametric polymorphism (universally quantified types)

For all types T:template<class T> class future;template<class T> class vector;template<class T> class unique_ptr;

A mapping of types:T -> future<T>

Type Constructor

Page 17: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Type constructorFunction lifting: then, transform, (Haskell:

fmap)

T -> future<T>fuction<S(T)> ->

function<future<S>(future<T>));

The Functor Pattern

Page 18: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Problem: Composing (chaining) async calls

future<HANDLE> async_open(string &);future<Buffer> async_read(HANDLE fh);In principle, this is the result:future<future<Buffer>> ffBuf =

async_open("foo").next(&async_read);

Asynchronous Chaining

Page 19: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Collapse two levels of futureasync_open("foo.cpp").next(&async_read).un

wrap().next(&async_process).unwrap();

Combination of next and unwrap called bind(Haskell: >>=, bind combines join with

fmap)In C++, next (then) can be overloaded to

serve as bind

Unwrap

Page 20: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Usage: conditional asynchrony, recursion

A future that is readymake_ready_future

future<int> fint = make_ready_future<int>(42);int i = fint.get(); // doesn’t block

Analogously, for containers:vector<int> v = {42};

Lifting a value

Page 21: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Functor pattern Type constructorFunction lifting (then, next, transform)

Collapsing (unwrap, concat)Value lifting (make_ready_future)

Monad Pattern

Page 22: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Type constructorValue lifting: make_ready_future()bind: combination of .next(f).unwrap() [or an

overload of next]

Usage of the future monad pattern: Composing libraries of async functions

Monad Pattern 2

Page 23: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

It’s all in the wristnext (or bind) checks for exceptions and

propagates them (without calling the continuation)

At the end of the chain, recover from exceptionasync_open("foo.cpp").next(&async_read).next(

parse).recover(&on_error);Exception monad

Implements short-circuitingCan be put on top of the future monad (monad

transformers)

Exceptions

Page 24: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Problem: Need N futures to proceed.Create a barrier, get all values, proceed.when_all: takes futures, returns future of

finished futuresClient gets, iterates, gets each, and proceeds

with valuesFunctional approach

Apply a regular function of n argument to n futures.

Lifting of n-ary functionswhen_all_done(futures).next(fn)Together with make_ready_future: applicative

functor

Applicative Pattern

Page 25: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

Problem: Wait for the first future to completewhen_any: takes futures, returns a future of

futures, at least one of them readyClient gets, iterates, checks is_ready, picks

value. proceedsFunctional approach

The OR combinator (like addition?)Combines two futures into oneAssoc.: (f1 OR f2) OR f3 = f1 OR (f2 OR f3)Neutral element: the “never” futurenever OR f = f = f OR neverDefines a monoid

Monoid Pattern

Page 26: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor.

New patterns based on functional programmingFunctorApplicative FunctorMonadMonoid

Composability and orthogonalityResult: Library of futures

Conclusions


Recommended