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.
Ad

More Related Content

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++ >
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
 
Антон Бикинеев, 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
 
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
 
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
 

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
ICF CIRCUIT
 
Intel open mp
Intel open mpIntel open mp
Intel open mp
Piyush Mittal
 
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 Studio
bryan 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
 
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 Studio
bryan 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
 
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
 
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
 
Ad

More from Platonov Sergey (20)

Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
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
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
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
 
Как мы уменьшили количество ошибок в 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
 
Ad

Recently uploaded (20)

WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AIScaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
danshalev
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
AxisTechnolabs
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& ConsiderationsDesigning AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Dinusha Kumarasiri
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
Societal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainabilitySocietal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainability
Jordi Cabot
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
Expand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchangeExpand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchange
Fexle Services Pvt. Ltd.
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Solidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license codeSolidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license code
aneelaramzan63
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AIScaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
danshalev
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
AxisTechnolabs
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& ConsiderationsDesigning AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Dinusha Kumarasiri
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
Societal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainabilitySocietal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainability
Jordi Cabot
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
Expand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchangeExpand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchange
Fexle Services Pvt. Ltd.
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Solidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license codeSolidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license code
aneelaramzan63
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 

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.