SlideShare a Scribd company logo
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Better Code: Concurrency
Sean Parent | Principal Scientist
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Better Code
! Regular Type
! Goal: Implement Complete and Efficient Types
! Algorithms
! Goal: No Raw Loops
! Data Structures
! Goal: No Incidental Data Structures
! Runtime Polymorphism
! Goal: No Raw Pointers
! Concurrency
! Goal: No Raw Synchronization Primitives
! …
2
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Common Themes
! Manage Relationships
! Understand the Fundamentals
! Code Simply
3
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Demo
4
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Concurrency
! Concurrency: when tasks start, run, and complete in overlapping time periods
! Parallelism: when two or more tasks execute simultaneously
! Why?
! Enable performance through parallelism
! Improve interactivity by handling user actions concurrent with processing and IO
5
http://docs.oracle.com/cd/E19455-01/806-5257/6je9h032b/index.html
© 2013 Adobe Systems Incorporated. All Rights Reserved.
No Raw Synchronization Primitives
6
© 2013 Adobe Systems Incorporated. All Rights Reserved.
What are raw synchronization primitives?
! Synchronization primitives are basic constructs such as:
! Mutex
! Atomic
! Semaphore
! Memory Fence
! Condition Variable
7
© 2014 Adobe Systems Incorporated. All Rights Reserved. 8
Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950)
8
© 2014 Adobe Systems Incorporated. All Rights Reserved. 8
Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950)
8
0 750 1500 2250 3000
GPU Vectorization Multi-thread Scalar (GFlops)
© 2014 Adobe Systems Incorporated. All Rights Reserved. 8
Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950)
8
OpenGL
OpenCL
CUDA
Direct Compute
C++ AMP
DirectX
0 750 1500 2250 3000
GPU Vectorization Multi-thread Scalar (GFlops)
© 2014 Adobe Systems Incorporated. All Rights Reserved. 8
Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950)
Intrinsics
Auto-vectorization
OpenCL
8
OpenGL
OpenCL
CUDA
Direct Compute
C++ AMP
DirectX
0 750 1500 2250 3000
GPU Vectorization Multi-thread Scalar (GFlops)
© 2014 Adobe Systems Incorporated. All Rights Reserved. 8
Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950)
Intrinsics
Auto-vectorization
OpenCL
8
TBB
GCD
OpenMP
C++11
OpenGL
OpenCL
CUDA
Direct Compute
C++ AMP
DirectX
0 750 1500 2250 3000
GPU Vectorization Multi-thread Scalar (GFlops)
© 2014 Adobe Systems Incorporated. All Rights Reserved. 8
Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950)
Intrinsics
Auto-vectorization
OpenCL
8
Straight C++
TBB
GCD
OpenMP
C++11
OpenGL
OpenCL
CUDA
Direct Compute
C++ AMP
DirectX
0 750 1500 2250 3000
GPU Vectorization Multi-thread Scalar (GFlops)
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Threads and Tasks
! Thread: Execution environment consisting of a stack and processor state running in parallel to other threads
! Task: A unit of work, often a function, to be executed on a thread
! Tasks are scheduled on a thread pool to optimize machine utilization
9
© 2014 Adobe Systems Incorporated. All Rights Reserved.
C++14 and Tasks
! C++14 does not have a task system
! Threads
! Futures (more on this)
10
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Amdahl’s Law
11
http://en.wikipedia.org/wiki/Amdahl%27s_law
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Amdahl’s Law
12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Processors
Performance
© 2014 Adobe Systems Incorporated. All Rights Reserved.
What Makes It Slow
! Starvation
! Latency
! Overhead
! Wait
13
Hartmut Kaiser - HPX
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
14
Object
thread
thread
thread
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
14
Object
thread
thread
thread
STOP
STOP
GO
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
14
Object
thread
thread
thread
STOP
STOP
GO
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
14
Object
thread
thread
thread
STOP
STOP
GO
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Minimize Locks
15
STOP
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Minimize Locks
15
STOP
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
! Portable Reference Implementation in C++14
! Windows - Window Thread Pool and PPL
! Apple - Grand Central Dispatch (libdispatch)
! open source, runs on Linux and Android
! Intel TBB - many platforms
! open source
! HPX - many platforms
! open source
16
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
17
http://docs.oracle.com/cd/E19253-01/816-5137/ggedn/index.html
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
Task
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
18
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
using lock_t = unique_lock<mutex>;
18
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
using lock_t = unique_lock<mutex>;
class notification_queue {
deque<function<void()>> _q;
mutex _mutex;
condition_variable _ready;
18
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
using lock_t = unique_lock<mutex>;
class notification_queue {
deque<function<void()>> _q;
mutex _mutex;
condition_variable _ready;
public:
void pop(function<void()>& x) {
lock_t lock{_mutex};
while (_q.empty()) _ready.wait(lock);
x = move(_q.front());
_q.pop_front();
}
18
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
using lock_t = unique_lock<mutex>;
class notification_queue {
deque<function<void()>> _q;
mutex _mutex;
condition_variable _ready;
public:
void pop(function<void()>& x) {
lock_t lock{_mutex};
while (_q.empty()) _ready.wait(lock);
x = move(_q.front());
_q.pop_front();
}
template<typename F>
void push(F&& f) {
{
lock_t lock{_mutex};
_q.emplace_back(forward<F>(f));
}
_ready.notify_one();
}
};
18
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
19
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
notification_queue _q;
19
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
notification_queue _q;
void run(unsigned i) {
while (true) {
function<void()> f;
_q.pop(f);
f();
}
}
19
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
notification_queue _q;
void run(unsigned i) {
while (true) {
function<void()> f;
_q.pop(f);
f();
}
}
public:
task_system() {
for (unsigned n = 0; n != _count; ++n) {
_threads.emplace_back([&, n]{ run(n); });
}
}
19
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
notification_queue _q;
void run(unsigned i) {
while (true) {
function<void()> f;
_q.pop(f);
f();
}
}
public:
task_system() {
for (unsigned n = 0; n != _count; ++n) {
_threads.emplace_back([&, n]{ run(n); });
}
}
~task_system() {
for (auto& e : _threads) e.join();
}
19
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
notification_queue _q;
void run(unsigned i) {
while (true) {
function<void()> f;
_q.pop(f);
f();
}
}
public:
task_system() {
for (unsigned n = 0; n != _count; ++n) {
_threads.emplace_back([&, n]{ run(n); });
}
}
~task_system() {
for (auto& e : _threads) e.join();
}
template <typename F>
void async_(F&& f) {
_q.push(forward<F>(f));
}
};
19
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
void done() {
{
unique_lock<mutex> lock{_mutex};
_done = true;
}
_ready.notify_all();
}
bool pop(function<void()>& x) {
lock_t lock{_mutex};
while (_q.empty() && !_done) _ready.wait(lock);
if (_q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
void push(F&& f) {
{
lock_t lock{_mutex};
_q.emplace_back(forward<F>(f));
20
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
void done() {
{
unique_lock<mutex> lock{_mutex};
_done = true;
}
_ready.notify_all();
}
bool pop(function<void()>& x) {
lock_t lock{_mutex};
while (_q.empty() && !_done) _ready.wait(lock);
if (_q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
void push(F&& f) {
{
lock_t lock{_mutex};
_q.emplace_back(forward<F>(f));
20
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
void done() {
{
unique_lock<mutex> lock{_mutex};
_done = true;
}
_ready.notify_all();
}
bool pop(function<void()>& x) {
lock_t lock{_mutex};
while (_q.empty() && !_done) _ready.wait(lock);
if (_q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
void push(F&& f) {
{
lock_t lock{_mutex};
_q.emplace_back(forward<F>(f));
20
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
void done() {
{
unique_lock<mutex> lock{_mutex};
_done = true;
}
_ready.notify_all();
}
bool pop(function<void()>& x) {
lock_t lock{_mutex};
while (_q.empty() && !_done) _ready.wait(lock);
if (_q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
void push(F&& f) {
{
lock_t lock{_mutex};
_q.emplace_back(forward<F>(f));
20
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
21
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
Task
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
21
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
Task
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
22
Object
thread
thread
thread
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
22
Object
thread
thread
thread
STOP
STOP
GO
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Why No Raw Synchronization Primitives?
22
Object
thread
thread
thread
STOP
STOP
GO
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
23
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
Task
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
23
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
Task
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
24
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
Task
Scheduler
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
vector<notification_queue> _q{_count};
atomic<unsigned> _index{0};
void run(unsigned i) {
while (true) {
function<void()> f;
if (!_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() {
for (auto& e : _q) e.done();
for (auto& e : _threads) e.join();
}
template <typename F>
void async_(F&& f) {
auto i = _index++;
_q[i % _count].push(forward<F>(f));
}
};
25
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
vector<notification_queue> _q{_count};
atomic<unsigned> _index{0};
void run(unsigned i) {
while (true) {
function<void()> f;
if (!_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() {
for (auto& e : _q) e.done();
for (auto& e : _threads) e.join();
}
template <typename F>
void async_(F&& f) {
auto i = _index++;
_q[i % _count].push(forward<F>(f));
}
};
25
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
vector<notification_queue> _q{_count};
atomic<unsigned> _index{0};
void run(unsigned i) {
while (true) {
function<void()> f;
if (!_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() {
for (auto& e : _q) e.done();
for (auto& e : _threads) e.join();
}
template <typename F>
void async_(F&& f) {
auto i = _index++;
_q[i % _count].push(forward<F>(f));
}
};
25
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
vector<notification_queue> _q{_count};
atomic<unsigned> _index{0};
void run(unsigned i) {
while (true) {
function<void()> f;
if (!_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() {
for (auto& e : _q) e.done();
for (auto& e : _threads) e.join();
}
template <typename F>
void async_(F&& f) {
auto i = _index++;
_q[i % _count].push(forward<F>(f));
}
};
25
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class task_system {
const unsigned _count{thread::hardware_concurrency()};
vector<thread> _threads;
vector<notification_queue> _q{_count};
atomic<unsigned> _index{0};
void run(unsigned i) {
while (true) {
function<void()> f;
if (!_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() {
for (auto& e : _q) e.done();
for (auto& e : _threads) e.join();
}
template <typename F>
void async_(F&& f) {
auto i = _index++;
_q[i % _count].push(forward<F>(f));
}
};
25
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
26
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
Task
Scheduler
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
26
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
Task
Scheduler
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
27
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
Task
Scheduler
Task Stealing
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
bool try_pop(function<void()>& x) {
lock_t lock{_mutex, try_to_lock};
if (!lock || _q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
bool try_push(F&& f) {
{
lock_t lock{_mutex, try_to_lock};
if (!lock) return false;
_q.emplace_back(forward<F>(f));
}
_ready.notify_one();
return true;
}
void done() {
{
unique_lock<mutex> lock{_mutex};
28
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
bool try_pop(function<void()>& x) {
lock_t lock{_mutex, try_to_lock};
if (!lock || _q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
bool try_push(F&& f) {
{
lock_t lock{_mutex, try_to_lock};
if (!lock) return false;
_q.emplace_back(forward<F>(f));
}
_ready.notify_one();
return true;
}
void done() {
{
unique_lock<mutex> lock{_mutex};
28
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
class notification_queue {
deque<function<void()>> _q;
bool _done{false};
mutex _mutex;
condition_variable _ready;
public:
bool try_pop(function<void()>& x) {
lock_t lock{_mutex, try_to_lock};
if (!lock || _q.empty()) return false;
x = move(_q.front());
_q.pop_front();
return true;
}
template<typename F>
bool try_push(F&& f) {
{
lock_t lock{_mutex, try_to_lock};
if (!lock) return false;
_q.emplace_back(forward<F>(f));
}
_ready.notify_one();
return true;
}
void done() {
{
unique_lock<mutex> lock{_mutex};
28
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
void run(unsigned i) {
while (true) {
function<void()> f;
for (unsigned n = 0; n != _count; ++n) {
if (_q[(i + n) % _count].try_pop(f)) break;
}
if (!f && !_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() { }
template <typename F>
void async_(F&& f) {
auto i = _index++;
for (unsigned n = 0; n != _count; ++n) {
if (_q[(i + n) % _count].try_push(forward<F>(f))) return;
}
_q[i % _count].push(forward<F>(f));
}
};
29
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
void run(unsigned i) {
while (true) {
function<void()> f;
for (unsigned n = 0; n != _count; ++n) {
if (_q[(i + n) % _count].try_pop(f)) break;
}
if (!f && !_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() { }
template <typename F>
void async_(F&& f) {
auto i = _index++;
for (unsigned n = 0; n != _count; ++n) {
if (_q[(i + n) % _count].try_push(forward<F>(f))) return;
}
_q[i % _count].push(forward<F>(f));
}
};
29
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
void run(unsigned i) {
while (true) {
function<void()> f;
for (unsigned n = 0; n != _count; ++n) {
if (_q[(i + n) % _count].try_pop(f)) break;
}
if (!f && !_q[i].pop(f)) break;
f();
}
}
public:
task_system() { }
~task_system() { }
template <typename F>
void async_(F&& f) {
auto i = _index++;
for (unsigned n = 0; n != _count; ++n) {
if (_q[(i + n) % _count].try_push(forward<F>(f))) return;
}
_q[i % _count].push(forward<F>(f));
}
};
29
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
30
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
Task
Scheduler
Task Stealing
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Building a Task System
30
Core Core Core…
Thread Thread Thread
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
.
.
.
Task
Task
Task
Task
Scheduler
Task Stealing
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Task System
! Within a few percentage points of Apple’s GCD (libdispatch) under load
! Can be improved by spinning more on try_pop in run
31
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
32
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); });
// Do Something
cout << x.get() << endl;
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
! Fibonacci is often used as an example for parallel algorithms
! Please stop…
32
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); });
// Do Something
cout << x.get() << endl;
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Public Service Announcement - How to Write Fibonacci
template <typename T, typename N, typename O>
T power(T x, N n, O op)
{
if (n == 0) return identity_element(op);
while ((n & 1) == 0) {
n >>= 1;
x = op(x, x);
}
T result = x;
n >>= 1;
while (n != 0) {
x = op(x, x);
if ((n & 1) != 0) result = op(result, x);
n >>= 1;
}
return result;
}
33
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Public Service Announcement - How to Write Fibonacci
template <typename T, typename N, typename O>
T power(T x, N n, O op)
{
if (n == 0) return identity_element(op);
while ((n & 1) == 0) {
n >>= 1;
x = op(x, x);
}
T result = x;
n >>= 1;
while (n != 0) {
x = op(x, x);
if ((n & 1) != 0) result = op(result, x);
n >>= 1;
}
return result;
}
33
Egyptian Multiplication (Russian Peasant Algorithm)
See “From Mathematics to Generic Programming” - Alex Stepanov and Dan Rose
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Public Service Announcement - How to Write Fibonacci
template <typename N>
struct multiply_2x2 {
array<N, 4> operator()(const array<N, 4>& x, const array<N, 4>& y)
{
return { x[0] * y[0] + x[1] * y[2], x[0] * y[1] + x[1] * y[3],
x[2] * y[0] + x[3] * y[2], x[2] * y[1] + x[3] * y[3] };
}
};
template <typename N>
array<N, 4> identity_element(const multiply_2x2<N>&) { return { N(1), N(0), N(0), N(1) }; }
template <typename R, typename N>
R fibonacci(N n) {
if (n == 0) return R(0);
return power(array<R, 4>{ 1, 1, 1, 0 }, N(n - 1), multiply_2x2<R>())[0];
}
34
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
19532821287077577316320149475962563324435429965918733969534051945716252578870156947666419876341501461288795
24335220236084625510912019560233744015438115196636156919962125642894303370113827800638002767411527927466669
86557837931882283206127149758323033485489348957259923072291290192820926433162752173086146001791258204269965
99360209593392020051848620284024473431398113674187202038684801753185386211128781082406177413832935545616876
06454065125954718029126547942894036981659206361019359291352135410376799082940320155702716115395031975973247
78216295763162965335669477766328506234524559346064757502593581344345781676764625878859011372729907372947851
14480895724561915035070255895291168685500088020132334587472177947814475467920160901706425856293597475465327
57575740077432034913428785189795354304734560307765078938767286539166799232817449361991523768149557632085371
04785970618843873153058239562756087906310781900497516959470973671389174570455520213512335079440336071203050
41446852210415650373210679322756258647511914611417360349681217380234224786080292021093192496490409832397066
83247054441763512526732455275419501683845206023007394959854279298297831204382115757645787692495583351402522
15272066244180900325938075362849179668095297118507191379833678873770459913639333955814212036990261617972113
25091840023055327607104316478190974300434647793363287601469996128023925829471557316688943339455429292871877
48774789204296166356536610796023919702109728472966709427334586344798048633944635211654971507261342768205479
32093175079888010130416027982506354182344034558742236701282666356934611294613123128389060036547327660245693
15151850018328483150645480029978935985161237074046158229354440701748339514575869547491750264542126364262224
72060048855462589961190475892101224280542898621594646662478564373572217775549876087685912030118551635668902
01034463998397732663888903650784161807091545252992759735213957415477729146008794314339156060445825107823511
66271892637923313014643880597879468444879060576786297460989627426663569682474293386740207436559426057944790
71193052258931590719386545525880429139747140181849169733838138446154843063123649290835584278078456131936457
55911722136946338180311600307896211668652895953778436464402382516362449718197385444149563131714002850338928
22274134603018094224837216321854717270452813824078425638747365249141118080783866506339945376239206700513391
87333107136069698189628284763245423299306272870457991293245741167533902274499963096566680922262516468582544
55785134982414412726124015815753818098466667145006988839178551800894370189025721992485208742915560261917752
28124660628996787166529678487268484905041328497297712688011639978376434280202452251550102240354169885185375
01584673881194047619720619603126534496759917893244478170702904446589571950228809157793897642423751814020998
99958161231477902295781100168670186738619861797138139854666281969548553740707356228616165539428076418408092
12047932816683005984504787929406356318097479755152035094682765918741610907637506902765294367561539803261388
35
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
15790155892833100345673846243104676900000936756893803676769777642059716492347060997973282994459039755683869
10568541105888505197986232161807165960864316652383369579251545877324797429523572491518310013505994095431367
23454418539676396422570487868443336735568511535850565172490141772333018072390350689838662532338266203548476
87722321662223383305226882245421258277211223435986491973881404168406609216954760818955479619408040043497601
35646408461148077885537891122888139618703907906033147416881433658136276942006644505679690480702792206520855
12245086839375655196861305232092138041808273198852928058246964575561801618520046644949262341864859342928965
21378574554544426221453176445385228867960454072522804961741905198550911362542849130027243353553345377968558
49780195976636516290598457219043489821358221206856924121139313137132134865741440892670003665555632446499775
56853514681289887391700907057970839124191923062570547772748610990924519168225326823578140721238189631411471
29610287340041050015549547086272721534936510345705849389706515725684266079756708385889612130516276472992631
59674474594901199950849178952149715987731953191759591623424021718579696778102054496598766846143959650647332
21985323521378108187030642875506951890343587181633604126397675020909133548480151135951824112432636080497447
37395896608759569909256138919905403404664655310556021101996525724843421071082933739200159651403373870955680
75656822683537933983982488022723770319785461480932302347255796621173892988541730741484707211664044157057536
04582256143224299859780683239696543855523783781413866750792868372058020433472254190336846843017198934115689
96526838242546875
35
0.72s to calculate
208,988 digits
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
36
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); });
// Do Something
cout << x.get() << endl;
f(…)->r
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
37
f(…) r
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
37
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
! Futures allow minimal code transformations to express dependencies
38
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures: What year is this?
! C++14 futures have:
! Exception Marshaling
! Sever Notification (broken promise)
39
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures: What year is this?
! C++14 futures lack:
! Continuations - .then()
! Joins - when_all()
! Cancelation
! Progress Monitoring (Except Ready)
! …
! And C++14 futures don’t compose (easily) to add these features
40
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
41
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
! Blocking on std::future.get() has two problems
! One thread resource is consumed, increasing contention
! Any subsequent non-dependent calculations on the task are also blocked
! C++14 doesn’t have continuations
! GCD has serialized queues and groups
! PPL has chained tasks
! TBB has flow graphs
! TS Concurrency will have them
! Boost futures have them now
42
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); });
future<void> y = x.then([](future<cpp_int> x){ cout << x.get() << endl; });
// Do something
y.wait();
43
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
44
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
auto x = async([]{ return fibonacci<cpp_int>(1'000'000); });
auto y = async([]{ return fibonacci<cpp_int>(2'000'000); });
auto z = when_all(std::move(x), std::move(y)).then([](auto f){
auto t = f.get();
return cpp_int(get<0>(t).get() * get<1>(t).get());
});
cout << z.get() << endl;
45
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
auto x = async([]{ return fibonacci<cpp_int>(1'000'000); });
auto y = async([]{ return fibonacci<cpp_int>(2'000'000); });
auto z = when_all(std::move(x), std::move(y)).then([](auto f){
auto t = f.get();
return cpp_int(get<0>(t).get() * get<1>(t).get());
});
cout << z.get() << endl;
45
f is a future tuple of futures
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
auto x = async([]{ return fibonacci<cpp_int>(1'000'000); });
auto y = async([]{ return fibonacci<cpp_int>(2'000'000); });
auto z = when_all(std::move(x), std::move(y)).then([](auto f){
auto t = f.get();
return cpp_int(get<0>(t).get() * get<1>(t).get());
});
cout << z.get() << endl;
45
f is a future tuple of futures
result is 626,964 digits
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
46
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); });
future<cpp_int> y = x.then([](future<cpp_int> x){ return cpp_int(x.get() * 2); });
future<cpp_int> z = x.then([](future<cpp_int> x){ return cpp_int(x.get() / 15); });
47
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); });
future<cpp_int> y = x.then([](future<cpp_int> x){ return cpp_int(x.get() * 2); });
future<cpp_int> z = x.then([](future<cpp_int> x){ return cpp_int(x.get() / 15); });
47
Assertion failed: (px != 0), function operator->, file shared_ptr.hpp, line 648.
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Continuations
! Desired behavior
! A future should behave as a regular type - a token for the actual value
! shared_futures let me pass them around and do multiple get() operations, but don’t fix continuations
! [at least with boost]
! Releasing the last instance of a future should cancel (no-op) any unexecuted, contributing, operations
48
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
49
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
49
shared
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
50
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
50
shared
shared
shared
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename>
struct result_of_; //not defined
template <typename R, typename... Args>
struct result_of_<R(Args...)> { using type = R; };
template <typename F>
using result_of_t_ = typename result_of_<F>::type;
51
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename>
struct result_of_; //not defined
template <typename R, typename... Args>
struct result_of_<R(Args...)> { using type = R; };
template <typename F>
using result_of_t_ = typename result_of_<F>::type;
51
result_of_t_<int(double)> -> int
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename> class packaged_task; //not defined
template <typename R>
class future {
shared_ptr</* ... */> _p;
public:
future() = default;
template <typename F>
auto then(F&& f) { }
const R& get() const { }
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const { }
};
52
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename> class packaged_task; //not defined
template <typename R>
class future {
shared_ptr</* ... */> _p;
public:
future() = default;
template <typename F>
auto then(F&& f) { }
const R& get() const { }
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const { }
};
52
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename> class packaged_task; //not defined
template <typename R>
class future {
shared_ptr</* ... */> _p;
public:
future() = default;
template <typename F>
auto then(F&& f) { }
const R& get() const { }
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const { }
};
52
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename> class packaged_task; //not defined
template <typename R>
class future {
shared_ptr</* ... */> _p;
public:
future() = default;
template <typename F>
auto then(F&& f) { }
const R& get() const { }
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const { }
};
52
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Building, The
template <typename> class packaged_task; //not defined
template <typename R>
class future {
shared_ptr</* ... */> _p;
public:
future() = default;
template <typename F>
auto then(F&& f) { }
const R& get() const { }
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const { }
};
52
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename> class packaged_task; //not defined
template <typename> class future;
template <typename S, typename F>
auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
template <typename R>
class future {
shared_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
Futures: Building, The
53
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename> class packaged_task; //not defined
template <typename> class future;
template <typename S, typename F>
auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
template <typename R>
class future {
shared_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
Futures: Building, The
53
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename> class packaged_task; //not defined
template <typename> class future;
template <typename S, typename F>
auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
template <typename R>
class future {
shared_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
Futures: Building, The
53
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename> class packaged_task; //not defined
template <typename> class future;
template <typename S, typename F>
auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
template <typename R>
class future {
shared_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr</* ... */> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { }
/* ... */
};
Futures: Building, The
53
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename S, typename F>
auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>> {
auto p = make_shared<shared<S>>(forward<F>(f));
return make_pair(packaged_task<S>(p), future<result_of_t_<S>>(p));
}
Futures: Building, The
54
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename S, typename F>
auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>> {
auto p = make_shared<shared<S>>(forward<F>(f));
return make_pair(packaged_task<S>(p), future<result_of_t_<S>>(p));
}
Futures: Building, The
54
package<int(double)>(f) -> { void(double), future<int> }
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
/* ... */
};
template <typename> struct shared; // not defined
template <typename R, typename... Args>
struct shared<R(Args...)> : shared_base<R> {
function<R(Args...)> _f;
template<typename F>
shared(F&& f) : _f(forward<F>(f)) { }
/* ... */
};
Futures: Building, The
55
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
/* ... */
};
template <typename> struct shared; // not defined
template <typename R, typename... Args>
struct shared<R(Args...)> : shared_base<R> {
function<R(Args...)> _f;
template<typename F>
shared(F&& f) : _f(forward<F>(f)) { }
/* ... */
};
Futures: Building, The
55
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
/* ... */
};
template <typename> struct shared; // not defined
template <typename R, typename... Args>
struct shared<R(Args...)> : shared_base<R> {
function<R(Args...)> _f;
template<typename F>
shared(F&& f) : _f(forward<F>(f)) { }
/* ... */
};
Futures: Building, The
55
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr<shared<R(Args...)>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr<shared<R(Args...)>> p) : _p(move(p)) { }
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const {
auto p = _p.lock();
if (p) (*p)(forward<A>(args)...);
}
};
Futures: Building, The
56
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr<shared<R(Args...)>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr<shared<R(Args...)>> p) : _p(move(p)) { }
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const {
auto p = _p.lock();
if (p) (*p)(forward<A>(args)...);
}
};
Futures: Building, The
56
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
weak_ptr<shared<R(Args...)>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit packaged_task(weak_ptr<shared<R(Args...)>> p) : _p(move(p)) { }
public:
packaged_task() = default;
template <typename... A>
void operator()(A&&... args) const {
auto p = _p.lock();
if (p) (*p)(forward<A>(args)...);
}
};
Futures: Building, The
56
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R, typename... Args>
struct shared<R(Args...)> : shared_base<R> {
function<R(Args...)> _f;
template<typename F>
shared(F&& f) : _f(forward<F>(f)) { }
template <typename... A>
void operator()(A&&... args) {
this->set(_f(forward<A>(args)...));
_f = nullptr;
}
};
Futures: Building, The
57
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R, typename... Args>
struct shared<R(Args...)> : shared_base<R> {
function<R(Args...)> _f;
template<typename F>
shared(F&& f) : _f(forward<F>(f)) { }
template <typename... A>
void operator()(A&&... args) {
this->set(_f(forward<A>(args)...));
_f = nullptr;
}
};
Futures: Building, The
57
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
void set(R&& r) {
vector<function<void()>> then;
{
lock_t lock{_mutex};
_r.push_back(move(r));
swap(_then, then);
}
_ready.notify_all();
for (const auto& f : then) _system.async_(move(f));
}
};
Futures: Building, The
58
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
void set(R&& r) {
vector<function<void()>> then;
{
lock_t lock{_mutex};
_r.push_back(move(r));
swap(_then, then);
}
_ready.notify_all();
for (const auto& f : then) _system.async_(move(f));
}
};
Futures: Building, The
58
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
class future {
shared_ptr<shared_base<R>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { }
public:
future() = default;
template <typename F>
auto then(F&& f) {
auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){
return f(p->_r.back());
});
_p->then(move(pack.first));
return pack.second;
}
const R& get() const { return _p->get(); }
};
Futures: Building, The
59
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
class future {
shared_ptr<shared_base<R>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { }
public:
future() = default;
template <typename F>
auto then(F&& f) {
auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){
return f(p->_r.back());
});
_p->then(move(pack.first));
return pack.second;
}
const R& get() const { return _p->get(); }
};
Futures: Building, The
59
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
class future {
shared_ptr<shared_base<R>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { }
public:
future() = default;
template <typename F>
auto then(F&& f) {
auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){
return f(p->_r.back());
});
_p->then(move(pack.first));
return pack.second;
}
const R& get() const { return _p->get(); }
};
Futures: Building, The
59
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
class future {
shared_ptr<shared_base<R>> _p;
template <typename S, typename F>
friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>;
explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { }
public:
future() = default;
template <typename F>
auto then(F&& f) {
auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){
return f(p->_r.back());
});
_p->then(move(pack.first));
return pack.second;
}
const R& get() const { return _p->get(); }
};
Futures: Building, The
59
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
void set(R&& r) { }
template <typename F>
void then(F&& f) {
bool resolved{false};
{
lock_t lock{_mutex};
if (_r.empty()) _then.push_back(forward<F>(f));
else resolved = true;
}
if (resolved) _system.async_(move(f));
}
const R& get() {
lock_t lock{_mutex};
while (_r.empty()) _ready.wait(lock);
return _r.back();
}
};
Futures: Building, The
60
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
void set(R&& r) { }
template <typename F>
void then(F&& f) {
bool resolved{false};
{
lock_t lock{_mutex};
if (_r.empty()) _then.push_back(forward<F>(f));
else resolved = true;
}
if (resolved) _system.async_(move(f));
}
const R& get() {
lock_t lock{_mutex};
while (_r.empty()) _ready.wait(lock);
return _r.back();
}
};
Futures: Building, The
60
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename R>
struct shared_base {
vector<R> _r; // optional
mutex _mutex;
condition_variable _ready;
vector<function<void()>> _then;
virtual ~shared_base() { }
void set(R&& r) { }
template <typename F>
void then(F&& f) {
bool resolved{false};
{
lock_t lock{_mutex};
if (_r.empty()) _then.push_back(forward<F>(f));
else resolved = true;
}
if (resolved) _system.async_(move(f));
}
const R& get() {
lock_t lock{_mutex};
while (_r.empty()) _ready.wait(lock);
return _r.back();
}
};
Futures: Building, The
60
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
61
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Futures
61
shared
shared
shared
© 2013 Adobe Systems Incorporated. All Rights Reserved.
template <typename F, typename ...Args>
auto async(F&& f, Args&&... args)
{
using result_type = result_of_t<F (Args...)>;
using packaged_type = packaged_task<result_type()>;
auto pack = package<result_type()>(bind(forward<F>(f), forward<Args>(args)...));
_system.async_(move(get<0>(pack)));
return get<1>(pack);
}
Futures: Building, The
62
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); });
future<cpp_int> y = x.then([](const cpp_int& x){ return cpp_int(x * 2); });
future<cpp_int> z = x.then([](const cpp_int& x){ return cpp_int(x / 15); });
cout << y.get() << endl;
cout << z.get() << endl;
63
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Futures: Continuations
future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); });
future<cpp_int> y = x.then([](const cpp_int& x){ return cpp_int(x * 2); });
future<cpp_int> z = x.then([](const cpp_int& x){ return cpp_int(x / 15); });
cout << y.get() << endl;
cout << z.get() << endl;
63
708449696358523830150
23614989878617461005
© 2014 Adobe Systems Incorporated. All Rights Reserved.
Property Models
64
© 2013 Adobe Systems Incorporated. All Rights Reserved.
What if we persist the graph?
65
© 2013 Adobe Systems Incorporated. All Rights Reserved.
What if we persist the graph?
! Allow multiple invocations of the tasks by setting the source values
! Each change triggers a notification to the sink values
! This is a reactive programming model and futures are known as behaviors
66
© 2013 Adobe Systems Incorporated. All Rights Reserved.
How do the graphs change during execution?
67
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Property Model
68
a
c
R{a,b,c} b
© 2013 Adobe Systems Incorporated. All Rights Reserved.
A function is a directed relationship
! We can remove the arrows by providing a package of functions to represent the relationship
! a = b * c

b = a / c

c = a / b
! This forms a type of constraint system called a property model
! Flow is determined by value, or cell, priority
! Cells can only have one in-edge for a given flow or the system is over constrained
69
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Property Model
70
sink
source
source
sink
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Property Models
! Reflowing a property model doesn’t require all relationships to be resolved
! The task representing them can still be executing concurrently
! This creates a single dependency graph that is appended to for each new flow and is pruned and unravels as
tasks are complete
71
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Property Model
72
source
source
sink
sink
source
sink
sink
© 2013 Adobe Systems Incorporated. All Rights Reserved.
Final Thoughts
! Perhaps representing such systems as if it where imperative code is not the correct approach
! Instead the a graph description can be compiled and statically validated
73
© 2014 Adobe Systems Incorporated. All Rights Reserved.

More Related Content

What's hot

Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
Sergey Platonov
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
Doug Hawkins
 
Clang tidy
Clang tidyClang tidy
Clang tidy
Yury Yafimachau
 
Verilator: Fast, Free, But for Me?
Verilator: Fast, Free, But for Me? Verilator: Fast, Free, But for Me?
Verilator: Fast, Free, But for Me? DVClub
 
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
Andrey Karpov
 
Code generation with javac plugin
Code generation with javac pluginCode generation with javac plugin
Code generation with javac plugin
Oleksandr Radchykov
 
Global Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealGlobal Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the Seal
Tzung-Bi Shih
 
Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-x
Andrey Karpov
 
How to make a large C++-code base manageable
How to make a large C++-code base manageableHow to make a large C++-code base manageable
How to make a large C++-code base manageable
corehard_by
 
PVS-Studio for Linux (CoreHard presentation)
PVS-Studio for Linux (CoreHard presentation)PVS-Studio for Linux (CoreHard presentation)
PVS-Studio for Linux (CoreHard presentation)
Andrey Karpov
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
David Rodenas
 
Js tacktalk team dev js testing performance
Js tacktalk team dev js testing performanceJs tacktalk team dev js testing performance
Js tacktalk team dev js testing performance
Артем Захарченко
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
Andrey Karpov
 
Objective-C Runtime overview
Objective-C Runtime overviewObjective-C Runtime overview
Objective-C Runtime overview
Fantageek
 
The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189
Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 102 of 212
The Ring programming language version 1.10 book - Part 102 of 212The Ring programming language version 1.10 book - Part 102 of 212
The Ring programming language version 1.10 book - Part 102 of 212
Mahmoud Samir Fayed
 
NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#
tcaesvk
 
Concurrency in Programming Languages
Concurrency in Programming LanguagesConcurrency in Programming Languages
Concurrency in Programming Languages
Yudong Li
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop Applications
Clare Macrae
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
Andrey Karpov
 

What's hot (20)

Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Clang tidy
Clang tidyClang tidy
Clang tidy
 
Verilator: Fast, Free, But for Me?
Verilator: Fast, Free, But for Me? Verilator: Fast, Free, But for Me?
Verilator: Fast, Free, But for Me?
 
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
 
Code generation with javac plugin
Code generation with javac pluginCode generation with javac plugin
Code generation with javac plugin
 
Global Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealGlobal Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the Seal
 
Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-x
 
How to make a large C++-code base manageable
How to make a large C++-code base manageableHow to make a large C++-code base manageable
How to make a large C++-code base manageable
 
PVS-Studio for Linux (CoreHard presentation)
PVS-Studio for Linux (CoreHard presentation)PVS-Studio for Linux (CoreHard presentation)
PVS-Studio for Linux (CoreHard presentation)
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
Js tacktalk team dev js testing performance
Js tacktalk team dev js testing performanceJs tacktalk team dev js testing performance
Js tacktalk team dev js testing performance
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
 
Objective-C Runtime overview
Objective-C Runtime overviewObjective-C Runtime overview
Objective-C Runtime overview
 
The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189
 
The Ring programming language version 1.10 book - Part 102 of 212
The Ring programming language version 1.10 book - Part 102 of 212The Ring programming language version 1.10 book - Part 102 of 212
The Ring programming language version 1.10 book - Part 102 of 212
 
NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#
 
Concurrency in Programming Languages
Concurrency in Programming LanguagesConcurrency in Programming Languages
Concurrency in Programming Languages
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop Applications
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
 

Similar to Better Code: Concurrency

Maximize the power of OSGi in AEM
Maximize the power of OSGi in AEM Maximize the power of OSGi in AEM
Maximize the power of OSGi in AEM
ICF CIRCUIT
 
ColdFusion 11 Overview - CFSummit 2013
ColdFusion 11 Overview - CFSummit 2013ColdFusion 11 Overview - CFSummit 2013
ColdFusion 11 Overview - CFSummit 2013
Rupesh Kumar
 
Getting Started with Adobe AIR 1.5
Getting Started with Adobe AIR 1.5Getting Started with Adobe AIR 1.5
Getting Started with Adobe AIR 1.5
Elad Elrom
 
Electron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easyElectron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easy
Ulrich Krause
 
Experience with C++11 in ArangoDB
Experience with C++11 in ArangoDBExperience with C++11 in ArangoDB
Experience with C++11 in ArangoDB
Max Neunhöffer
 
C# Production Debugging Made Easy
 C# Production Debugging Made Easy C# Production Debugging Made Easy
C# Production Debugging Made Easy
Alon Fliess
 
Cross-Platform Mobile Development in Visual Studio
Cross-Platform Mobile Development in Visual StudioCross-Platform Mobile Development in Visual Studio
Cross-Platform Mobile Development in Visual Studiobryan costanich
 
OpenSouthCode 2016 - Accenture DevOps Platform 2016-05-07
OpenSouthCode 2016  - Accenture DevOps Platform 2016-05-07OpenSouthCode 2016  - Accenture DevOps Platform 2016-05-07
OpenSouthCode 2016 - Accenture DevOps Platform 2016-05-07
Jorge Hidalgo
 
Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...
Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...
Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...
mfrancis
 
Android task manager project presentation
Android task manager project presentationAndroid task manager project presentation
Android task manager project presentation
Akhilesh Jaiswal
 
Raising ux bar with offline first design
Raising ux bar with offline first designRaising ux bar with offline first design
Raising ux bar with offline first design
Kyrylo Reznykov
 
DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.
Vlad Fedosov
 
Eclipse Training - Main eclipse ecosystem classes
Eclipse Training - Main eclipse ecosystem classesEclipse Training - Main eclipse ecosystem classes
Eclipse Training - Main eclipse ecosystem classes
Luca D'Onofrio
 
NodeJS
NodeJSNodeJS
NodeJS
LinkMe Srl
 
Using JavaScript to Build HTML5 Tools (Ian Maffett)
Using JavaScript to Build HTML5 Tools (Ian Maffett)Using JavaScript to Build HTML5 Tools (Ian Maffett)
Using JavaScript to Build HTML5 Tools (Ian Maffett)
Future Insights
 
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
New and cool in OSGi R7 - David Bosschaert & Carsten ZiegelerNew and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
mfrancis
 
server side Swift
server side Swift server side Swift
server side Swift
NormanSutorius
 
Eclipse summit-2010
Eclipse summit-2010Eclipse summit-2010
Eclipse summit-2010
Intland Software GmbH
 
Deploying Web Apps with PaaS and Docker Tools
Deploying Web Apps with PaaS and Docker ToolsDeploying Web Apps with PaaS and Docker Tools
Deploying Web Apps with PaaS and Docker Tools
Eddie Lau
 

Similar to Better Code: Concurrency (20)

Maximize the power of OSGi in AEM
Maximize the power of OSGi in AEM Maximize the power of OSGi in AEM
Maximize the power of OSGi in AEM
 
Intel open mp
Intel open mpIntel open mp
Intel open mp
 
ColdFusion 11 Overview - CFSummit 2013
ColdFusion 11 Overview - CFSummit 2013ColdFusion 11 Overview - CFSummit 2013
ColdFusion 11 Overview - CFSummit 2013
 
Getting Started with Adobe AIR 1.5
Getting Started with Adobe AIR 1.5Getting Started with Adobe AIR 1.5
Getting Started with Adobe AIR 1.5
 
Electron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easyElectron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easy
 
Experience with C++11 in ArangoDB
Experience with C++11 in ArangoDBExperience with C++11 in ArangoDB
Experience with C++11 in ArangoDB
 
C# Production Debugging Made Easy
 C# Production Debugging Made Easy C# Production Debugging Made Easy
C# Production Debugging Made Easy
 
Cross-Platform Mobile Development in Visual Studio
Cross-Platform Mobile Development in Visual StudioCross-Platform Mobile Development in Visual Studio
Cross-Platform Mobile Development in Visual Studio
 
OpenSouthCode 2016 - Accenture DevOps Platform 2016-05-07
OpenSouthCode 2016  - Accenture DevOps Platform 2016-05-07OpenSouthCode 2016  - Accenture DevOps Platform 2016-05-07
OpenSouthCode 2016 - Accenture DevOps Platform 2016-05-07
 
Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...
Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...
Creating an all-purpose REST API for Cloud services using OSGi and Sling - C ...
 
Android task manager project presentation
Android task manager project presentationAndroid task manager project presentation
Android task manager project presentation
 
Raising ux bar with offline first design
Raising ux bar with offline first designRaising ux bar with offline first design
Raising ux bar with offline first design
 
DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.
 
Eclipse Training - Main eclipse ecosystem classes
Eclipse Training - Main eclipse ecosystem classesEclipse Training - Main eclipse ecosystem classes
Eclipse Training - Main eclipse ecosystem classes
 
NodeJS
NodeJSNodeJS
NodeJS
 
Using JavaScript to Build HTML5 Tools (Ian Maffett)
Using JavaScript to Build HTML5 Tools (Ian Maffett)Using JavaScript to Build HTML5 Tools (Ian Maffett)
Using JavaScript to Build HTML5 Tools (Ian Maffett)
 
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
New and cool in OSGi R7 - David Bosschaert & Carsten ZiegelerNew and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
 
server side Swift
server side Swift server side Swift
server side Swift
 
Eclipse summit-2010
Eclipse summit-2010Eclipse summit-2010
Eclipse summit-2010
 
Deploying Web Apps with PaaS and Docker Tools
Deploying Web Apps with PaaS and Docker ToolsDeploying Web Apps with PaaS and Docker Tools
Deploying Web Apps with PaaS and Docker Tools
 

More from Platonov Sergey

Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Platonov Sergey
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
Platonov Sergey
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Platonov Sergey
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
Platonov Sergey
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Platonov Sergey
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Platonov Sergey
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Platonov Sergey
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Platonov Sergey
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практике
Platonov Sergey
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутов
Platonov Sergey
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++
Platonov Sergey
 
C++ exceptions
C++ exceptionsC++ exceptions
C++ exceptions
Platonov Sergey
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Platonov Sergey
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычислений
Platonov Sergey
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08
Platonov Sergey
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Platonov Sergey
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Platonov Sergey
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим жить
Platonov Sergey
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
Platonov Sergey
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузера
Platonov Sergey
 

More from Platonov Sergey (20)

Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практике
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутов
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++
 
C++ exceptions
C++ exceptionsC++ exceptions
C++ exceptions
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычислений
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим жить
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузера
 

Recently uploaded

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
kalichargn70th171
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
Srikant77
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 

Recently uploaded (20)

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 

Better Code: Concurrency

  • 1. © 2014 Adobe Systems Incorporated. All Rights Reserved. Better Code: Concurrency Sean Parent | Principal Scientist
  • 2. © 2014 Adobe Systems Incorporated. All Rights Reserved. Better Code ! Regular Type ! Goal: Implement Complete and Efficient Types ! Algorithms ! Goal: No Raw Loops ! Data Structures ! Goal: No Incidental Data Structures ! Runtime Polymorphism ! Goal: No Raw Pointers ! Concurrency ! Goal: No Raw Synchronization Primitives ! … 2
  • 3. © 2014 Adobe Systems Incorporated. All Rights Reserved. Common Themes ! Manage Relationships ! Understand the Fundamentals ! Code Simply 3
  • 4. © 2013 Adobe Systems Incorporated. All Rights Reserved. Demo 4
  • 5. © 2014 Adobe Systems Incorporated. All Rights Reserved. Concurrency ! Concurrency: when tasks start, run, and complete in overlapping time periods ! Parallelism: when two or more tasks execute simultaneously ! Why? ! Enable performance through parallelism ! Improve interactivity by handling user actions concurrent with processing and IO 5 http://docs.oracle.com/cd/E19455-01/806-5257/6je9h032b/index.html
  • 6. © 2013 Adobe Systems Incorporated. All Rights Reserved. No Raw Synchronization Primitives 6
  • 7. © 2013 Adobe Systems Incorporated. All Rights Reserved. What are raw synchronization primitives? ! Synchronization primitives are basic constructs such as: ! Mutex ! Atomic ! Semaphore ! Memory Fence ! Condition Variable 7
  • 8. © 2014 Adobe Systems Incorporated. All Rights Reserved. 8 Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950) 8
  • 9. © 2014 Adobe Systems Incorporated. All Rights Reserved. 8 Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950) 8 0 750 1500 2250 3000 GPU Vectorization Multi-thread Scalar (GFlops)
  • 10. © 2014 Adobe Systems Incorporated. All Rights Reserved. 8 Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950) 8 OpenGL OpenCL CUDA Direct Compute C++ AMP DirectX 0 750 1500 2250 3000 GPU Vectorization Multi-thread Scalar (GFlops)
  • 11. © 2014 Adobe Systems Incorporated. All Rights Reserved. 8 Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950) Intrinsics Auto-vectorization OpenCL 8 OpenGL OpenCL CUDA Direct Compute C++ AMP DirectX 0 750 1500 2250 3000 GPU Vectorization Multi-thread Scalar (GFlops)
  • 12. © 2014 Adobe Systems Incorporated. All Rights Reserved. 8 Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950) Intrinsics Auto-vectorization OpenCL 8 TBB GCD OpenMP C++11 OpenGL OpenCL CUDA Direct Compute C++ AMP DirectX 0 750 1500 2250 3000 GPU Vectorization Multi-thread Scalar (GFlops)
  • 13. © 2014 Adobe Systems Incorporated. All Rights Reserved. 8 Desktop Compute Power (8-core 3.5GHz Sandy Bridge + AMD Radeon 6950) Intrinsics Auto-vectorization OpenCL 8 Straight C++ TBB GCD OpenMP C++11 OpenGL OpenCL CUDA Direct Compute C++ AMP DirectX 0 750 1500 2250 3000 GPU Vectorization Multi-thread Scalar (GFlops)
  • 14. © 2014 Adobe Systems Incorporated. All Rights Reserved. Threads and Tasks ! Thread: Execution environment consisting of a stack and processor state running in parallel to other threads ! Task: A unit of work, often a function, to be executed on a thread ! Tasks are scheduled on a thread pool to optimize machine utilization 9
  • 15. © 2014 Adobe Systems Incorporated. All Rights Reserved. C++14 and Tasks ! C++14 does not have a task system ! Threads ! Futures (more on this) 10
  • 16. © 2014 Adobe Systems Incorporated. All Rights Reserved. Amdahl’s Law 11 http://en.wikipedia.org/wiki/Amdahl%27s_law
  • 17. © 2014 Adobe Systems Incorporated. All Rights Reserved. Amdahl’s Law 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Processors Performance
  • 18. © 2014 Adobe Systems Incorporated. All Rights Reserved. What Makes It Slow ! Starvation ! Latency ! Overhead ! Wait 13 Hartmut Kaiser - HPX
  • 19. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 14 Object thread thread thread
  • 20. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 14 Object thread thread thread STOP STOP GO
  • 21. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 14 Object thread thread thread STOP STOP GO
  • 22. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 14 Object thread thread thread STOP STOP GO
  • 23. © 2013 Adobe Systems Incorporated. All Rights Reserved. Minimize Locks 15 STOP
  • 24. © 2013 Adobe Systems Incorporated. All Rights Reserved. Minimize Locks 15 STOP
  • 25. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System ! Portable Reference Implementation in C++14 ! Windows - Window Thread Pool and PPL ! Apple - Grand Central Dispatch (libdispatch) ! open source, runs on Linux and Android ! Intel TBB - many platforms ! open source ! HPX - many platforms ! open source 16
  • 26. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 17 http://docs.oracle.com/cd/E19253-01/816-5137/ggedn/index.html Core Core Core… Thread Thread Thread . . . Task Task Task Task
  • 27. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 18
  • 28. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System using lock_t = unique_lock<mutex>; 18
  • 29. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System using lock_t = unique_lock<mutex>; class notification_queue { deque<function<void()>> _q; mutex _mutex; condition_variable _ready; 18
  • 30. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System using lock_t = unique_lock<mutex>; class notification_queue { deque<function<void()>> _q; mutex _mutex; condition_variable _ready; public: void pop(function<void()>& x) { lock_t lock{_mutex}; while (_q.empty()) _ready.wait(lock); x = move(_q.front()); _q.pop_front(); } 18
  • 31. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System using lock_t = unique_lock<mutex>; class notification_queue { deque<function<void()>> _q; mutex _mutex; condition_variable _ready; public: void pop(function<void()>& x) { lock_t lock{_mutex}; while (_q.empty()) _ready.wait(lock); x = move(_q.front()); _q.pop_front(); } template<typename F> void push(F&& f) { { lock_t lock{_mutex}; _q.emplace_back(forward<F>(f)); } _ready.notify_one(); } }; 18
  • 32. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 19
  • 33. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; notification_queue _q; 19
  • 34. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; notification_queue _q; void run(unsigned i) { while (true) { function<void()> f; _q.pop(f); f(); } } 19
  • 35. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; notification_queue _q; void run(unsigned i) { while (true) { function<void()> f; _q.pop(f); f(); } } public: task_system() { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n]{ run(n); }); } } 19
  • 36. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; notification_queue _q; void run(unsigned i) { while (true) { function<void()> f; _q.pop(f); f(); } } public: task_system() { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n]{ run(n); }); } } ~task_system() { for (auto& e : _threads) e.join(); } 19
  • 37. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; notification_queue _q; void run(unsigned i) { while (true) { function<void()> f; _q.pop(f); f(); } } public: task_system() { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n]{ run(n); }); } } ~task_system() { for (auto& e : _threads) e.join(); } template <typename F> void async_(F&& f) { _q.push(forward<F>(f)); } }; 19
  • 38. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: void done() { { unique_lock<mutex> lock{_mutex}; _done = true; } _ready.notify_all(); } bool pop(function<void()>& x) { lock_t lock{_mutex}; while (_q.empty() && !_done) _ready.wait(lock); if (_q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> void push(F&& f) { { lock_t lock{_mutex}; _q.emplace_back(forward<F>(f)); 20
  • 39. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: void done() { { unique_lock<mutex> lock{_mutex}; _done = true; } _ready.notify_all(); } bool pop(function<void()>& x) { lock_t lock{_mutex}; while (_q.empty() && !_done) _ready.wait(lock); if (_q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> void push(F&& f) { { lock_t lock{_mutex}; _q.emplace_back(forward<F>(f)); 20
  • 40. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: void done() { { unique_lock<mutex> lock{_mutex}; _done = true; } _ready.notify_all(); } bool pop(function<void()>& x) { lock_t lock{_mutex}; while (_q.empty() && !_done) _ready.wait(lock); if (_q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> void push(F&& f) { { lock_t lock{_mutex}; _q.emplace_back(forward<F>(f)); 20
  • 41. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: void done() { { unique_lock<mutex> lock{_mutex}; _done = true; } _ready.notify_all(); } bool pop(function<void()>& x) { lock_t lock{_mutex}; while (_q.empty() && !_done) _ready.wait(lock); if (_q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> void push(F&& f) { { lock_t lock{_mutex}; _q.emplace_back(forward<F>(f)); 20
  • 42. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 21 Core Core Core… Thread Thread Thread . . . Task Task Task Task
  • 43. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 21 Core Core Core… Thread Thread Thread . . . Task Task Task Task
  • 44. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 22 Object thread thread thread
  • 45. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 22 Object thread thread thread STOP STOP GO
  • 46. © 2013 Adobe Systems Incorporated. All Rights Reserved. Why No Raw Synchronization Primitives? 22 Object thread thread thread STOP STOP GO
  • 47. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 23 Core Core Core… Thread Thread Thread . . . Task Task Task Task
  • 48. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 23 Core Core Core… Thread Thread Thread . . . Task Task Task Task
  • 49. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 24 Core Core Core… Thread Thread Thread . . . Task Task Task . . . Task Task Task . . . Task Task Task Task Scheduler
  • 50. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; vector<notification_queue> _q{_count}; atomic<unsigned> _index{0}; void run(unsigned i) { while (true) { function<void()> f; if (!_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { for (auto& e : _q) e.done(); for (auto& e : _threads) e.join(); } template <typename F> void async_(F&& f) { auto i = _index++; _q[i % _count].push(forward<F>(f)); } }; 25
  • 51. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; vector<notification_queue> _q{_count}; atomic<unsigned> _index{0}; void run(unsigned i) { while (true) { function<void()> f; if (!_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { for (auto& e : _q) e.done(); for (auto& e : _threads) e.join(); } template <typename F> void async_(F&& f) { auto i = _index++; _q[i % _count].push(forward<F>(f)); } }; 25
  • 52. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; vector<notification_queue> _q{_count}; atomic<unsigned> _index{0}; void run(unsigned i) { while (true) { function<void()> f; if (!_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { for (auto& e : _q) e.done(); for (auto& e : _threads) e.join(); } template <typename F> void async_(F&& f) { auto i = _index++; _q[i % _count].push(forward<F>(f)); } }; 25
  • 53. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; vector<notification_queue> _q{_count}; atomic<unsigned> _index{0}; void run(unsigned i) { while (true) { function<void()> f; if (!_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { for (auto& e : _q) e.done(); for (auto& e : _threads) e.join(); } template <typename F> void async_(F&& f) { auto i = _index++; _q[i % _count].push(forward<F>(f)); } }; 25
  • 54. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class task_system { const unsigned _count{thread::hardware_concurrency()}; vector<thread> _threads; vector<notification_queue> _q{_count}; atomic<unsigned> _index{0}; void run(unsigned i) { while (true) { function<void()> f; if (!_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { for (auto& e : _q) e.done(); for (auto& e : _threads) e.join(); } template <typename F> void async_(F&& f) { auto i = _index++; _q[i % _count].push(forward<F>(f)); } }; 25
  • 55. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 26 Core Core Core… Thread Thread Thread . . . Task Task Task . . . Task Task Task . . . Task Task Task Task Scheduler
  • 56. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 26 Core Core Core… Thread Thread Thread . . . Task Task Task . . . Task Task Task . . . Task Task Task Task Scheduler
  • 57. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 27 Core Core Core… Thread Thread Thread . . . Task Task Task . . . Task Task Task . . . Task Task Task Task Scheduler Task Stealing
  • 58. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: bool try_pop(function<void()>& x) { lock_t lock{_mutex, try_to_lock}; if (!lock || _q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> bool try_push(F&& f) { { lock_t lock{_mutex, try_to_lock}; if (!lock) return false; _q.emplace_back(forward<F>(f)); } _ready.notify_one(); return true; } void done() { { unique_lock<mutex> lock{_mutex}; 28
  • 59. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: bool try_pop(function<void()>& x) { lock_t lock{_mutex, try_to_lock}; if (!lock || _q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> bool try_push(F&& f) { { lock_t lock{_mutex, try_to_lock}; if (!lock) return false; _q.emplace_back(forward<F>(f)); } _ready.notify_one(); return true; } void done() { { unique_lock<mutex> lock{_mutex}; 28
  • 60. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System class notification_queue { deque<function<void()>> _q; bool _done{false}; mutex _mutex; condition_variable _ready; public: bool try_pop(function<void()>& x) { lock_t lock{_mutex, try_to_lock}; if (!lock || _q.empty()) return false; x = move(_q.front()); _q.pop_front(); return true; } template<typename F> bool try_push(F&& f) { { lock_t lock{_mutex, try_to_lock}; if (!lock) return false; _q.emplace_back(forward<F>(f)); } _ready.notify_one(); return true; } void done() { { unique_lock<mutex> lock{_mutex}; 28
  • 61. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System void run(unsigned i) { while (true) { function<void()> f; for (unsigned n = 0; n != _count; ++n) { if (_q[(i + n) % _count].try_pop(f)) break; } if (!f && !_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { } template <typename F> void async_(F&& f) { auto i = _index++; for (unsigned n = 0; n != _count; ++n) { if (_q[(i + n) % _count].try_push(forward<F>(f))) return; } _q[i % _count].push(forward<F>(f)); } }; 29
  • 62. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System void run(unsigned i) { while (true) { function<void()> f; for (unsigned n = 0; n != _count; ++n) { if (_q[(i + n) % _count].try_pop(f)) break; } if (!f && !_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { } template <typename F> void async_(F&& f) { auto i = _index++; for (unsigned n = 0; n != _count; ++n) { if (_q[(i + n) % _count].try_push(forward<F>(f))) return; } _q[i % _count].push(forward<F>(f)); } }; 29
  • 63. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System void run(unsigned i) { while (true) { function<void()> f; for (unsigned n = 0; n != _count; ++n) { if (_q[(i + n) % _count].try_pop(f)) break; } if (!f && !_q[i].pop(f)) break; f(); } } public: task_system() { } ~task_system() { } template <typename F> void async_(F&& f) { auto i = _index++; for (unsigned n = 0; n != _count; ++n) { if (_q[(i + n) % _count].try_push(forward<F>(f))) return; } _q[i % _count].push(forward<F>(f)); } }; 29
  • 64. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 30 Core Core Core… Thread Thread Thread . . . Task Task Task . . . Task Task Task . . . Task Task Task Task Scheduler Task Stealing
  • 65. © 2014 Adobe Systems Incorporated. All Rights Reserved. Building a Task System 30 Core Core Core… Thread Thread Thread . . . Task Task Task . . . Task Task Task . . . Task Task Task Task Scheduler Task Stealing
  • 66. © 2014 Adobe Systems Incorporated. All Rights Reserved. Task System ! Within a few percentage points of Apple’s GCD (libdispatch) under load ! Can be improved by spinning more on try_pop in run 31
  • 67. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 32 future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); }); // Do Something cout << x.get() << endl;
  • 68. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures ! Fibonacci is often used as an example for parallel algorithms ! Please stop… 32 future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); }); // Do Something cout << x.get() << endl;
  • 69. © 2014 Adobe Systems Incorporated. All Rights Reserved. Public Service Announcement - How to Write Fibonacci template <typename T, typename N, typename O> T power(T x, N n, O op) { if (n == 0) return identity_element(op); while ((n & 1) == 0) { n >>= 1; x = op(x, x); } T result = x; n >>= 1; while (n != 0) { x = op(x, x); if ((n & 1) != 0) result = op(result, x); n >>= 1; } return result; } 33
  • 70. © 2014 Adobe Systems Incorporated. All Rights Reserved. Public Service Announcement - How to Write Fibonacci template <typename T, typename N, typename O> T power(T x, N n, O op) { if (n == 0) return identity_element(op); while ((n & 1) == 0) { n >>= 1; x = op(x, x); } T result = x; n >>= 1; while (n != 0) { x = op(x, x); if ((n & 1) != 0) result = op(result, x); n >>= 1; } return result; } 33 Egyptian Multiplication (Russian Peasant Algorithm) See “From Mathematics to Generic Programming” - Alex Stepanov and Dan Rose
  • 71. © 2014 Adobe Systems Incorporated. All Rights Reserved. Public Service Announcement - How to Write Fibonacci template <typename N> struct multiply_2x2 { array<N, 4> operator()(const array<N, 4>& x, const array<N, 4>& y) { return { x[0] * y[0] + x[1] * y[2], x[0] * y[1] + x[1] * y[3], x[2] * y[0] + x[3] * y[2], x[2] * y[1] + x[3] * y[3] }; } }; template <typename N> array<N, 4> identity_element(const multiply_2x2<N>&) { return { N(1), N(0), N(0), N(1) }; } template <typename R, typename N> R fibonacci(N n) { if (n == 0) return R(0); return power(array<R, 4>{ 1, 1, 1, 0 }, N(n - 1), multiply_2x2<R>())[0]; } 34
  • 72. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 19532821287077577316320149475962563324435429965918733969534051945716252578870156947666419876341501461288795 24335220236084625510912019560233744015438115196636156919962125642894303370113827800638002767411527927466669 86557837931882283206127149758323033485489348957259923072291290192820926433162752173086146001791258204269965 99360209593392020051848620284024473431398113674187202038684801753185386211128781082406177413832935545616876 06454065125954718029126547942894036981659206361019359291352135410376799082940320155702716115395031975973247 78216295763162965335669477766328506234524559346064757502593581344345781676764625878859011372729907372947851 14480895724561915035070255895291168685500088020132334587472177947814475467920160901706425856293597475465327 57575740077432034913428785189795354304734560307765078938767286539166799232817449361991523768149557632085371 04785970618843873153058239562756087906310781900497516959470973671389174570455520213512335079440336071203050 41446852210415650373210679322756258647511914611417360349681217380234224786080292021093192496490409832397066 83247054441763512526732455275419501683845206023007394959854279298297831204382115757645787692495583351402522 15272066244180900325938075362849179668095297118507191379833678873770459913639333955814212036990261617972113 25091840023055327607104316478190974300434647793363287601469996128023925829471557316688943339455429292871877 48774789204296166356536610796023919702109728472966709427334586344798048633944635211654971507261342768205479 32093175079888010130416027982506354182344034558742236701282666356934611294613123128389060036547327660245693 15151850018328483150645480029978935985161237074046158229354440701748339514575869547491750264542126364262224 72060048855462589961190475892101224280542898621594646662478564373572217775549876087685912030118551635668902 01034463998397732663888903650784161807091545252992759735213957415477729146008794314339156060445825107823511 66271892637923313014643880597879468444879060576786297460989627426663569682474293386740207436559426057944790 71193052258931590719386545525880429139747140181849169733838138446154843063123649290835584278078456131936457 55911722136946338180311600307896211668652895953778436464402382516362449718197385444149563131714002850338928 22274134603018094224837216321854717270452813824078425638747365249141118080783866506339945376239206700513391 87333107136069698189628284763245423299306272870457991293245741167533902274499963096566680922262516468582544 55785134982414412726124015815753818098466667145006988839178551800894370189025721992485208742915560261917752 28124660628996787166529678487268484905041328497297712688011639978376434280202452251550102240354169885185375 01584673881194047619720619603126534496759917893244478170702904446589571950228809157793897642423751814020998 99958161231477902295781100168670186738619861797138139854666281969548553740707356228616165539428076418408092 12047932816683005984504787929406356318097479755152035094682765918741610907637506902765294367561539803261388 35
  • 73. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 15790155892833100345673846243104676900000936756893803676769777642059716492347060997973282994459039755683869 10568541105888505197986232161807165960864316652383369579251545877324797429523572491518310013505994095431367 23454418539676396422570487868443336735568511535850565172490141772333018072390350689838662532338266203548476 87722321662223383305226882245421258277211223435986491973881404168406609216954760818955479619408040043497601 35646408461148077885537891122888139618703907906033147416881433658136276942006644505679690480702792206520855 12245086839375655196861305232092138041808273198852928058246964575561801618520046644949262341864859342928965 21378574554544426221453176445385228867960454072522804961741905198550911362542849130027243353553345377968558 49780195976636516290598457219043489821358221206856924121139313137132134865741440892670003665555632446499775 56853514681289887391700907057970839124191923062570547772748610990924519168225326823578140721238189631411471 29610287340041050015549547086272721534936510345705849389706515725684266079756708385889612130516276472992631 59674474594901199950849178952149715987731953191759591623424021718579696778102054496598766846143959650647332 21985323521378108187030642875506951890343587181633604126397675020909133548480151135951824112432636080497447 37395896608759569909256138919905403404664655310556021101996525724843421071082933739200159651403373870955680 75656822683537933983982488022723770319785461480932302347255796621173892988541730741484707211664044157057536 04582256143224299859780683239696543855523783781413866750792868372058020433472254190336846843017198934115689 96526838242546875 35 0.72s to calculate 208,988 digits
  • 74. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 36 future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); }); // Do Something cout << x.get() << endl;
  • 75. f(…)->r © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 37
  • 76. f(…) r © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 37
  • 77. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures ! Futures allow minimal code transformations to express dependencies 38
  • 78. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures: What year is this? ! C++14 futures have: ! Exception Marshaling ! Sever Notification (broken promise) 39
  • 79. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures: What year is this? ! C++14 futures lack: ! Continuations - .then() ! Joins - when_all() ! Cancelation ! Progress Monitoring (Except Ready) ! … ! And C++14 futures don’t compose (easily) to add these features 40
  • 80. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations 41
  • 81. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations ! Blocking on std::future.get() has two problems ! One thread resource is consumed, increasing contention ! Any subsequent non-dependent calculations on the task are also blocked ! C++14 doesn’t have continuations ! GCD has serialized queues and groups ! PPL has chained tasks ! TBB has flow graphs ! TS Concurrency will have them ! Boost futures have them now 42
  • 82. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations future<cpp_int> x = async([]{ return fibonacci<cpp_int>(1'000'000); }); future<void> y = x.then([](future<cpp_int> x){ cout << x.get() << endl; }); // Do something y.wait(); 43
  • 83. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 44
  • 84. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations auto x = async([]{ return fibonacci<cpp_int>(1'000'000); }); auto y = async([]{ return fibonacci<cpp_int>(2'000'000); }); auto z = when_all(std::move(x), std::move(y)).then([](auto f){ auto t = f.get(); return cpp_int(get<0>(t).get() * get<1>(t).get()); }); cout << z.get() << endl; 45
  • 85. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations auto x = async([]{ return fibonacci<cpp_int>(1'000'000); }); auto y = async([]{ return fibonacci<cpp_int>(2'000'000); }); auto z = when_all(std::move(x), std::move(y)).then([](auto f){ auto t = f.get(); return cpp_int(get<0>(t).get() * get<1>(t).get()); }); cout << z.get() << endl; 45 f is a future tuple of futures
  • 86. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations auto x = async([]{ return fibonacci<cpp_int>(1'000'000); }); auto y = async([]{ return fibonacci<cpp_int>(2'000'000); }); auto z = when_all(std::move(x), std::move(y)).then([](auto f){ auto t = f.get(); return cpp_int(get<0>(t).get() * get<1>(t).get()); }); cout << z.get() << endl; 45 f is a future tuple of futures result is 626,964 digits
  • 87. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 46
  • 88. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); }); future<cpp_int> y = x.then([](future<cpp_int> x){ return cpp_int(x.get() * 2); }); future<cpp_int> z = x.then([](future<cpp_int> x){ return cpp_int(x.get() / 15); }); 47
  • 89. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); }); future<cpp_int> y = x.then([](future<cpp_int> x){ return cpp_int(x.get() * 2); }); future<cpp_int> z = x.then([](future<cpp_int> x){ return cpp_int(x.get() / 15); }); 47 Assertion failed: (px != 0), function operator->, file shared_ptr.hpp, line 648.
  • 90. © 2014 Adobe Systems Incorporated. All Rights Reserved. Continuations ! Desired behavior ! A future should behave as a regular type - a token for the actual value ! shared_futures let me pass them around and do multiple get() operations, but don’t fix continuations ! [at least with boost] ! Releasing the last instance of a future should cancel (no-op) any unexecuted, contributing, operations 48
  • 91. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 49
  • 92. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 49 shared
  • 93. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 50
  • 94. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 50 shared shared shared
  • 95. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> struct result_of_; //not defined template <typename R, typename... Args> struct result_of_<R(Args...)> { using type = R; }; template <typename F> using result_of_t_ = typename result_of_<F>::type; 51
  • 96. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> struct result_of_; //not defined template <typename R, typename... Args> struct result_of_<R(Args...)> { using type = R; }; template <typename F> using result_of_t_ = typename result_of_<F>::type; 51 result_of_t_<int(double)> -> int
  • 97. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> class packaged_task; //not defined template <typename R> class future { shared_ptr</* ... */> _p; public: future() = default; template <typename F> auto then(F&& f) { } const R& get() const { } }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { } }; 52
  • 98. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> class packaged_task; //not defined template <typename R> class future { shared_ptr</* ... */> _p; public: future() = default; template <typename F> auto then(F&& f) { } const R& get() const { } }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { } }; 52
  • 99. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> class packaged_task; //not defined template <typename R> class future { shared_ptr</* ... */> _p; public: future() = default; template <typename F> auto then(F&& f) { } const R& get() const { } }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { } }; 52
  • 100. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> class packaged_task; //not defined template <typename R> class future { shared_ptr</* ... */> _p; public: future() = default; template <typename F> auto then(F&& f) { } const R& get() const { } }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { } }; 52
  • 101. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Building, The template <typename> class packaged_task; //not defined template <typename R> class future { shared_ptr</* ... */> _p; public: future() = default; template <typename F> auto then(F&& f) { } const R& get() const { } }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { } }; 52
  • 102. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename> class packaged_task; //not defined template <typename> class future; template <typename S, typename F> auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; template <typename R> class future { shared_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; Futures: Building, The 53
  • 103. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename> class packaged_task; //not defined template <typename> class future; template <typename S, typename F> auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; template <typename R> class future { shared_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; Futures: Building, The 53
  • 104. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename> class packaged_task; //not defined template <typename> class future; template <typename S, typename F> auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; template <typename R> class future { shared_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; Futures: Building, The 53
  • 105. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename> class packaged_task; //not defined template <typename> class future; template <typename S, typename F> auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; template <typename R> class future { shared_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr</* ... */> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr</* ... */> p) : _p(move(p)) { } /* ... */ }; Futures: Building, The 53
  • 106. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename S, typename F> auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>> { auto p = make_shared<shared<S>>(forward<F>(f)); return make_pair(packaged_task<S>(p), future<result_of_t_<S>>(p)); } Futures: Building, The 54
  • 107. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename S, typename F> auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>> { auto p = make_shared<shared<S>>(forward<F>(f)); return make_pair(packaged_task<S>(p), future<result_of_t_<S>>(p)); } Futures: Building, The 54 package<int(double)>(f) -> { void(double), future<int> }
  • 108. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } /* ... */ }; template <typename> struct shared; // not defined template <typename R, typename... Args> struct shared<R(Args...)> : shared_base<R> { function<R(Args...)> _f; template<typename F> shared(F&& f) : _f(forward<F>(f)) { } /* ... */ }; Futures: Building, The 55
  • 109. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } /* ... */ }; template <typename> struct shared; // not defined template <typename R, typename... Args> struct shared<R(Args...)> : shared_base<R> { function<R(Args...)> _f; template<typename F> shared(F&& f) : _f(forward<F>(f)) { } /* ... */ }; Futures: Building, The 55
  • 110. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } /* ... */ }; template <typename> struct shared; // not defined template <typename R, typename... Args> struct shared<R(Args...)> : shared_base<R> { function<R(Args...)> _f; template<typename F> shared(F&& f) : _f(forward<F>(f)) { } /* ... */ }; Futures: Building, The 55
  • 111. © 2013 Adobe Systems Incorporated. All Rights Reserved. template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr<shared<R(Args...)>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr<shared<R(Args...)>> p) : _p(move(p)) { } public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { auto p = _p.lock(); if (p) (*p)(forward<A>(args)...); } }; Futures: Building, The 56
  • 112. © 2013 Adobe Systems Incorporated. All Rights Reserved. template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr<shared<R(Args...)>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr<shared<R(Args...)>> p) : _p(move(p)) { } public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { auto p = _p.lock(); if (p) (*p)(forward<A>(args)...); } }; Futures: Building, The 56
  • 113. © 2013 Adobe Systems Incorporated. All Rights Reserved. template<typename R, typename ...Args > class packaged_task<R (Args...)> { weak_ptr<shared<R(Args...)>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit packaged_task(weak_ptr<shared<R(Args...)>> p) : _p(move(p)) { } public: packaged_task() = default; template <typename... A> void operator()(A&&... args) const { auto p = _p.lock(); if (p) (*p)(forward<A>(args)...); } }; Futures: Building, The 56
  • 114. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R, typename... Args> struct shared<R(Args...)> : shared_base<R> { function<R(Args...)> _f; template<typename F> shared(F&& f) : _f(forward<F>(f)) { } template <typename... A> void operator()(A&&... args) { this->set(_f(forward<A>(args)...)); _f = nullptr; } }; Futures: Building, The 57
  • 115. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R, typename... Args> struct shared<R(Args...)> : shared_base<R> { function<R(Args...)> _f; template<typename F> shared(F&& f) : _f(forward<F>(f)) { } template <typename... A> void operator()(A&&... args) { this->set(_f(forward<A>(args)...)); _f = nullptr; } }; Futures: Building, The 57
  • 116. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } void set(R&& r) { vector<function<void()>> then; { lock_t lock{_mutex}; _r.push_back(move(r)); swap(_then, then); } _ready.notify_all(); for (const auto& f : then) _system.async_(move(f)); } }; Futures: Building, The 58
  • 117. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } void set(R&& r) { vector<function<void()>> then; { lock_t lock{_mutex}; _r.push_back(move(r)); swap(_then, then); } _ready.notify_all(); for (const auto& f : then) _system.async_(move(f)); } }; Futures: Building, The 58
  • 118. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> class future { shared_ptr<shared_base<R>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { } public: future() = default; template <typename F> auto then(F&& f) { auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){ return f(p->_r.back()); }); _p->then(move(pack.first)); return pack.second; } const R& get() const { return _p->get(); } }; Futures: Building, The 59
  • 119. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> class future { shared_ptr<shared_base<R>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { } public: future() = default; template <typename F> auto then(F&& f) { auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){ return f(p->_r.back()); }); _p->then(move(pack.first)); return pack.second; } const R& get() const { return _p->get(); } }; Futures: Building, The 59
  • 120. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> class future { shared_ptr<shared_base<R>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { } public: future() = default; template <typename F> auto then(F&& f) { auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){ return f(p->_r.back()); }); _p->then(move(pack.first)); return pack.second; } const R& get() const { return _p->get(); } }; Futures: Building, The 59
  • 121. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> class future { shared_ptr<shared_base<R>> _p; template <typename S, typename F> friend auto package(F&& f) -> pair<packaged_task<S>, future<result_of_t_<S>>>; explicit future(shared_ptr<shared_base<R>> p) : _p(move(p)) { } public: future() = default; template <typename F> auto then(F&& f) { auto pack = package<result_of_t<F(R)>()>([p = _p, f = forward<F>(f)](){ return f(p->_r.back()); }); _p->then(move(pack.first)); return pack.second; } const R& get() const { return _p->get(); } }; Futures: Building, The 59
  • 122. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } void set(R&& r) { } template <typename F> void then(F&& f) { bool resolved{false}; { lock_t lock{_mutex}; if (_r.empty()) _then.push_back(forward<F>(f)); else resolved = true; } if (resolved) _system.async_(move(f)); } const R& get() { lock_t lock{_mutex}; while (_r.empty()) _ready.wait(lock); return _r.back(); } }; Futures: Building, The 60
  • 123. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } void set(R&& r) { } template <typename F> void then(F&& f) { bool resolved{false}; { lock_t lock{_mutex}; if (_r.empty()) _then.push_back(forward<F>(f)); else resolved = true; } if (resolved) _system.async_(move(f)); } const R& get() { lock_t lock{_mutex}; while (_r.empty()) _ready.wait(lock); return _r.back(); } }; Futures: Building, The 60
  • 124. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename R> struct shared_base { vector<R> _r; // optional mutex _mutex; condition_variable _ready; vector<function<void()>> _then; virtual ~shared_base() { } void set(R&& r) { } template <typename F> void then(F&& f) { bool resolved{false}; { lock_t lock{_mutex}; if (_r.empty()) _then.push_back(forward<F>(f)); else resolved = true; } if (resolved) _system.async_(move(f)); } const R& get() { lock_t lock{_mutex}; while (_r.empty()) _ready.wait(lock); return _r.back(); } }; Futures: Building, The 60
  • 125. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 61
  • 126. © 2014 Adobe Systems Incorporated. All Rights Reserved. Futures 61 shared shared shared
  • 127. © 2013 Adobe Systems Incorporated. All Rights Reserved. template <typename F, typename ...Args> auto async(F&& f, Args&&... args) { using result_type = result_of_t<F (Args...)>; using packaged_type = packaged_task<result_type()>; auto pack = package<result_type()>(bind(forward<F>(f), forward<Args>(args)...)); _system.async_(move(get<0>(pack))); return get<1>(pack); } Futures: Building, The 62
  • 128. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); }); future<cpp_int> y = x.then([](const cpp_int& x){ return cpp_int(x * 2); }); future<cpp_int> z = x.then([](const cpp_int& x){ return cpp_int(x / 15); }); cout << y.get() << endl; cout << z.get() << endl; 63
  • 129. © 2013 Adobe Systems Incorporated. All Rights Reserved. Futures: Continuations future<cpp_int> x = async([]{ return fibonacci<cpp_int>(100); }); future<cpp_int> y = x.then([](const cpp_int& x){ return cpp_int(x * 2); }); future<cpp_int> z = x.then([](const cpp_int& x){ return cpp_int(x / 15); }); cout << y.get() << endl; cout << z.get() << endl; 63 708449696358523830150 23614989878617461005
  • 130. © 2014 Adobe Systems Incorporated. All Rights Reserved. Property Models 64
  • 131. © 2013 Adobe Systems Incorporated. All Rights Reserved. What if we persist the graph? 65
  • 132. © 2013 Adobe Systems Incorporated. All Rights Reserved. What if we persist the graph? ! Allow multiple invocations of the tasks by setting the source values ! Each change triggers a notification to the sink values ! This is a reactive programming model and futures are known as behaviors 66
  • 133. © 2013 Adobe Systems Incorporated. All Rights Reserved. How do the graphs change during execution? 67
  • 134. © 2013 Adobe Systems Incorporated. All Rights Reserved. Property Model 68 a c R{a,b,c} b
  • 135. © 2013 Adobe Systems Incorporated. All Rights Reserved. A function is a directed relationship ! We can remove the arrows by providing a package of functions to represent the relationship ! a = b * c
 b = a / c
 c = a / b ! This forms a type of constraint system called a property model ! Flow is determined by value, or cell, priority ! Cells can only have one in-edge for a given flow or the system is over constrained 69
  • 136. © 2013 Adobe Systems Incorporated. All Rights Reserved. Property Model 70 sink source source sink
  • 137. © 2013 Adobe Systems Incorporated. All Rights Reserved. Property Models ! Reflowing a property model doesn’t require all relationships to be resolved ! The task representing them can still be executing concurrently ! This creates a single dependency graph that is appended to for each new flow and is pruned and unravels as tasks are complete 71
  • 138. © 2013 Adobe Systems Incorporated. All Rights Reserved. Property Model 72 source source sink sink source sink sink
  • 139. © 2013 Adobe Systems Incorporated. All Rights Reserved. Final Thoughts ! Perhaps representing such systems as if it where imperative code is not the correct approach ! Instead the a graph description can be compiled and statically validated 73
  • 140. © 2014 Adobe Systems Incorporated. All Rights Reserved.