bartosz milewski concurrency first class functions generic programming memory management (move...
TRANSCRIPT
![Page 1: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/1.jpg)
![Page 2: Bartosz Milewski Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/2.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/3.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/4.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/5.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/6.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/7.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/8.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/9.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/10.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/11.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/12.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/13.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/14.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/15.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/16.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/17.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/18.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/19.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/20.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/21.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/22.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/23.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/24.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/25.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062619/5516b1f4550346a25b8b5ae5/html5/thumbnails/26.jpg)
New patterns based on functional programmingFunctorApplicative FunctorMonadMonoid
Composability and orthogonalityResult: Library of futures
Conclusions