SlideShare uma empresa Scribd logo
1 de 40
Baixar para ler offline
Functional Patterns
For C++ Multithreading
Ovidiu Farauanu
Summary
1. Design Patterns and OOP popularity
2. Multithreading and OOP
3. Functional Design for Multithreaded programming
A design pattern systematically names, motivates, and explains a general
design that addresses a recurring design problem. It describes the problem, the
solution, when to apply the solution, and its consequences.
A mix of guidelines, templates and construction advice
(1) Design Patterns - The Celebrities: GoF
Some well known patterns*:
● Creational: Singleton, Factory, Builder, etc;
● Structural: Adapter, Proxy, Facade, Decorator, etc;
● Behavioural: Command, Interpreter, State, Strategy, Visitor, Observer, Mediator, etc.
*They are the same in all languages like: C++, Java, C#, etc. And well known.
(Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides)
Why is this? Oh… well, all those languages are object oriented.
(1) Design Patterns - the wrong level of
abstraction?
It is logical to use common strategies to solve recurring problems. In really
abstract languages it is possible to formalize those strategies and put them
into a library. (Peter Norvig, Paul Graham, Edgar Holleis)
Patterns are not "symptoms of not having enough abstraction in your code", but
are symptoms of having not enough means of abstraction in your language.
A good alternative to Object Oriented Design patterns is Aspect Oriented
Programming. (Java annotation, Python decorators)
(1) Macros (not preproc.) / Templates
● You modify/upgrade/specialize/build the language, adding some code to your libraries ...
● It’s all about the macro expander? Just string replacements and not syntax aware!
● Programmable programming language (LISP family)
● Data is code and security threats (not if happens at compile time only)
(1) Meta-programming
Other types of patterns:
● Architectural patterns
● Transactional patterns
● Concurrency patterns: critical zone, lock object, guarded suspension, balking, scheduler, read/write lock, producer/consumer, two
step termination, double buffering, asynchronous processing, future, thread pool, double check locking, active object, monitor object,
thread specific storage, leader/followers
But … what about some “functional patterns”?
They are not like some UML, object composition recipes, code snippets, etc.
But more related to the properties of types (types theory) in the compiler’s type system. (like: transitive immutability,
function purity, etc)
(2) Systems Programming & Multithreading
I used to be obsessed with Object Oriented Design Patterns, but “as an
engineer I found that I have to stay pragmatic”. The reason is:
Multi-threaded programming is really, really hard.
(especially when not designed carefully)
The problem is shared, mutable data: OOP encourages both.
(2) Sharing + Mutation = Data Race
● Composability: OOP has been very successful because engineers
solve problems by dividing them in smaller (or easier to solve)
subproblems
● Objects do not compose in the presence of concurrency
● OOP-style abstractions hide sharing and mutation
● Problem: Sharing + Mutation = Data Race
● Locking: Locking itself doesn’t compose
● Multicore programming: control over mutations (incl. CPU cache
inconsistencies)
Why I am using “multithreading” instead of “concurrency”?
Most of the talks are going something like:
(a) parallelism is important, so
(b) let’s talk about concurrency.
● Concurrency is concerned with non-deterministic composition of
programs
● Parallelism is concerned with asymptotic efficiency of programs with
deterministic behavior
Concurrency is required to implement parallelism, but it is also required to
implement sequentiality too. Concurrency is not relevant to parallelism.
(2) Concurrency is dangerous!
(2) Concurrency and design decisions
Multithreading is normally painful and must be managed with a lot of care and
very good design.
There are a lot of means out there to reach a safe multithreading in your
software.
Fact is that a lot of software at least C++ software do not use them.
Florentin Picioroaga
(2) Systems Programming
I’m sorry that I long ago coined the term “objects” for this topic, because it gets
many people to focus on the lesser idea. The big idea is “messaging”.
-- Alan Key
Concurrency is not hard (if done with proper tools), locks and threads
synchronization are hard.
Two pillars:
● Careful design of your software
● Good compiler infrastructure (or an “über” static code checker ~ formal
verification?) ;
POSA (Pattern Oriented Software
Architecture)
Volumes: 1 (1996), 2 (2000), 3 (2003), 4-5 (2007)
Frank Buschmann, Kevlin Henney, Douglas C. Schmidt
https://www.dre.vanderbilt.edu/~schmidt/POSA/
Lock Free Synchronization
● Compare and swap
● Test and set
● Fetch and add
● Read-copy-update
● Transactional Memory (Software / Hardware in development)
Require hardware support, Lock-free is not wait-free (Wait-free synchronization much harder, Usually
specifiable only given a fixed number of threads); implementations of common data structures are
available; Lock-free synchronization does not solve contention.
Boost.Lockfree & C++11 STL?
FP is an eternal promise
FP, not a magic bullet, still have to use spinlocks, memory barriers, etc.
We are systems programmers and need to use a lot of IOs, network, files, etc.
→ programmer must control the usage of paradigms.
But what about parallel computing (multi-core programming)?
Think function programming as “opposed” to object orientation.
Function types separates data from behavior.
Dijkstra: “Object-oriented programming is an exceptionally bad idea which could only have originated in California”.
But he was wrong (and arogant), it actually originates in Norway (Simula in 60’s);
Side-effects
C doesn't define the order of the side effects (another reason to avoid side
effects).
#include <stdio .h>
int foo(int n) {printf("Foo got %dn", n); return(0);}
int bar(int n) {printf("Bar got %dn", n); return(0);}
int main(int argc, char *argv[]) {
int m = 0;
int (*(fun_array[3]))();
int i = 1; int ii = i/++i; printf("ni/++i = %d, ",ii);
fun_array[1] = foo; fun_array[2] = bar;
(fun_array[++m])(++m);
}
(3) Immutable data and more
Referential Transparency
● an expression can be replaced with its value without changing the behavior of the program
● the same results for a given set of inputs at any point in time (pure functions)
This allows memoization (automatic caching) and parallelization.
No side effects → functions can be evaluated in parallel trivially. (Function that “does” nothing)
Advantage: Immutable sharing is never contentious ; no order dependencies
Purity: a contract between functions and their callers: The implementation of a pure function does not access global
mutable state.
Transitive “const” in C++
struct A {
A(): x_{ new int} {}
~A() { delete x_; }
int& x() { return *x_; }
const int& x() const { return *x_; }
private:
int* x_;
};
However, it is still possible to write to *x_ from within const member functions of A.
This makes it possible for const member functions to have side-effects on the class which are unexpected by the user.
Transitive “const” in C++
C++11's smart pointers also have the property of not being transitively const
pointer std::unique_ptr::get() const;
typename std::add_lvalue_reference<T>::type operator*() const;
pointer operator->() const;
These methods all return non-const pointers and references, even if the method is called on a const std::unique_ptr
instance.
Transitive “const” in C++
template<class T, class Deleter = std::default_delete<T>>
class transitive_ptr : public std::unique_ptr<T,Deleter>
{
public: // inherit typedefs for the sake of completeness
typedef typename std::unique_ptr<T,Deleter>::pointer pointer;
typedef typename std::unique_ptr<T,Deleter>::element_type element_type;
typedef typename std::unique_ptr<T,Deleter>::deleter_type deleter_type;
typedef const typename std::remove_pointer<pointer>::type* const_pointer;
using std::unique_ptr<T,Deleter>::unique_ptr;
// add transitive const version of get()
pointer get() { return std::unique_ptr<T,Deleter>::get(); }
const_pointer get() const { return std::unique_ptr<T,Deleter>::get(); }
// add transitive const version of operator*()
typename std::add_lvalue_reference<T>::type
operator*() { return *get(); }
typename std::add_lvalue_reference<const T>::type operator*() const { return *get(); }
Transitive “const” in C++
// add transitive const version of operator->()
pointer operator->() { return get(); }
const_pointer operator->() const { return get();}
};
Function purity
● Global variables (references, location referenced pointers and static storage, incl. locals) cannot
be written to
● Such variables cannot be read from, either unless they are invariant (immutable)
● Pure functions can only call other pure functions
● Parameters to a pure function can be mutable but calls cannot be cached
Note: Purity is not always desirable or achievable, not a silver bullet
Other advantages of purity
● Pure functions can be executed asynchronously. (std::async) This means that not only can the
function be executed lazily (for instance using a std::promise), it can also be farmed out to
another core (this will become increasingly important as more cores become commonplace).
● They can be hot swapped (meaning replaced at runtime), because they do not rely on any global
initialization or termination state.
(3) Function as object (functor)
Functor - is simply any object that can be called as if it is a function, an object
of a class that defines operator().
In this case function composition is similar to object composition, but with a
subtle difference: behavior and data are not coupled.
⇒ Increased modularity: Because of functional purity, a part of a program
cannot mess with another. → Easy refactoring
(3) Composition
// C++14
#include <utility>
template<typename G, typename F>
auto operator*(G&& g, F&& f) { return [g,f](auto&& t) { return
g(f(std::forward<decltype(t)>(t))); }; }
// Usage sample
auto const f = [](int v) { return v - 1.f; };
auto const g = [](float v) { return static_cast<int>(v); };
auto const h = g * f;
int main(int argc, const char* argv[]) {
return h(1);
}
(3) Applicative / Concatenative
This is the basic reason Unix pipes are so powerful: they form a rudimentary
string-based concatenative programming language.
Lazy evaluation: offers iterators that never invalidate (a problem that occurs
when traversing shared mutable containers).
The type of a concatenative function is formulated so that it takes any number
of inputs, uses only the topmost of these, and returns the unused input
followed by actual output. These functions are essentially operating on a
list-like data structure, one that allows removal and insertion only at one end.
And any programmer worth his salt can tell you what that structure is called….
A STACK
Partial application
using namespace std;
using namespace std::placeholders;
template<typename T>
T add(T left, T right) { return left + right; }
int main() {
auto bound_function = std::bind(add<int>, _1, 6); // Here _1 is a placeholder
}
Problem: neither the compiler nor the runtime will ever complain!
template<typename T, typename X, typename Y>
auto cancel(T func, X left, Y right)->function<decltype(func(left, right))(X)> {
return bind(func, left, _1);
}
int main() {
auto bound_function = cancel(add<int>, 6, 11);
cout << bound_function(22) << endl;
}
// bind generates a forwarding call wrapper for f.
// Calling this wrapper is equivalent to invoking f with some of its arguments bound to args.
// Side effects can be “ignored” or “denied” via partial application ...
First class citizens
● Functions as parameters
● Functions as return values
Memoization & Thunking
Memoization is an old term, which often means tabling a function's result.
Probably, no modern compiler does that because it's extremely expensive??
Lambda lifting: an expression containing a free variable is replaced by a
function applied to that variable. (similar to “move field” refactoring operation
on OOP designs)
Monadic lifting...
(3) Types are functions, not classes
Typedefs of pointer to functions?
How do you define a “callback” in Java? An interface with a single method, and
a class that implements that interface.
Suspenders
template<class T>
class Susp {
public:
explicit Susp(std::function<T()> f)
: _f(f)
{}
T get() { return _f(); }
private:
std::function<T()> _f;
};
int x = 2;
int y = 3;
Susp<int> sum([x, y]() { return x + y; });
...
int z = sum.get();
● If the function is not pure, we may get different values each time;
● if the function has side effects, these may happen multiple times;
● if the function is expensive, the performance will suffer.
All these problems may be addressed by memoizing the value.
I would like it to be simple, something like:
auto CounterFactory = [](int j) {
auto i = j;
return [i]() {
i++;
return i;
};
};
Thanks to ...
● Andrei Alexandrescu & Walter Bright (D and C++)
● Bartosz Milewski (Haskell and C++, D devel.)
● Scott Wlaschin ( )
● Also thanks to Rust and Go communities

Mais conteúdo relacionado

Mais procurados

Why Java Sucks and C# Rocks (Final)
Why Java Sucks and C# Rocks (Final)Why Java Sucks and C# Rocks (Final)
Why Java Sucks and C# Rocks (Final)
jeffz
 

Mais procurados (20)

Groovy / comparison with java
Groovy / comparison with javaGroovy / comparison with java
Groovy / comparison with java
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 
Java vs. C/C++
Java vs. C/C++Java vs. C/C++
Java vs. C/C++
 
2018 cosup-delete unused python code safely - english
2018 cosup-delete unused python code safely - english2018 cosup-delete unused python code safely - english
2018 cosup-delete unused python code safely - english
 
PHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing InsanityPHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing Insanity
 
C++ vs C#
C++ vs C#C++ vs C#
C++ vs C#
 
Algorithm and Programming (Procedure and Function)
Algorithm and Programming (Procedure and Function)Algorithm and Programming (Procedure and Function)
Algorithm and Programming (Procedure and Function)
 
An Execution-Semantic and Content-and-Context-Based Code-Clone Detection and ...
An Execution-Semantic and Content-and-Context-Based Code-Clone Detection and ...An Execution-Semantic and Content-and-Context-Based Code-Clone Detection and ...
An Execution-Semantic and Content-and-Context-Based Code-Clone Detection and ...
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
 
DConf 2016: Keynote by Walter Bright
DConf 2016: Keynote by Walter Bright DConf 2016: Keynote by Walter Bright
DConf 2016: Keynote by Walter Bright
 
Algorithm and Programming (Branching Structure)
Algorithm and Programming (Branching Structure)Algorithm and Programming (Branching Structure)
Algorithm and Programming (Branching Structure)
 
Google Dart
Google DartGoogle Dart
Google Dart
 
Why Java Sucks and C# Rocks (Final)
Why Java Sucks and C# Rocks (Final)Why Java Sucks and C# Rocks (Final)
Why Java Sucks and C# Rocks (Final)
 
Go lang introduction
Go lang introductionGo lang introduction
Go lang introduction
 
Learn To Code: Introduction to c
Learn To Code: Introduction to cLearn To Code: Introduction to c
Learn To Code: Introduction to c
 
Klee introduction
Klee  introductionKlee  introduction
Klee introduction
 
Contracts in Ruby - Vladyslav Hesal
Contracts in Ruby - Vladyslav HesalContracts in Ruby - Vladyslav Hesal
Contracts in Ruby - Vladyslav Hesal
 
Lecture 1
Lecture 1Lecture 1
Lecture 1
 
Monte Carlo C++
Monte Carlo C++Monte Carlo C++
Monte Carlo C++
 
c# usage,applications and advantages
c# usage,applications and advantages c# usage,applications and advantages
c# usage,applications and advantages
 

Destaque

Destaque (20)

Intro. to prog. c++
Intro. to prog. c++Intro. to prog. c++
Intro. to prog. c++
 
Domain Specific Languages and C++ Code Generation
Domain Specific Languages and C++ Code GenerationDomain Specific Languages and C++ Code Generation
Domain Specific Languages and C++ Code Generation
 
Florentin Picioroaga - C++ by choice
Florentin Picioroaga - C++ by choiceFlorentin Picioroaga - C++ by choice
Florentin Picioroaga - C++ by choice
 
Smart Pointers
Smart PointersSmart Pointers
Smart Pointers
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
Effective stl notes
Effective stl notesEffective stl notes
Effective stl notes
 
High Order Function Computations in c++14 (C++ Dev Meetup Iasi)
High Order Function Computations in c++14 (C++ Dev Meetup Iasi)High Order Function Computations in c++14 (C++ Dev Meetup Iasi)
High Order Function Computations in c++14 (C++ Dev Meetup Iasi)
 
Dependency Injection in C++ (Community Days 2015)
Dependency Injection in C++ (Community Days 2015)Dependency Injection in C++ (Community Days 2015)
Dependency Injection in C++ (Community Days 2015)
 
Effective c++notes
Effective c++notesEffective c++notes
Effective c++notes
 
Modern C++
Modern C++Modern C++
Modern C++
 
C traps and pitfalls for C++ programmers
C traps and pitfalls for C++ programmersC traps and pitfalls for C++ programmers
C traps and pitfalls for C++ programmers
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and delete
 
Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())
 
Operator Overloading
Operator OverloadingOperator Overloading
Operator Overloading
 
STL Algorithms In Action
STL Algorithms In ActionSTL Algorithms In Action
STL Algorithms In Action
 
Multithreading 101
Multithreading 101Multithreading 101
Multithreading 101
 
C++ Dependency Management 2.0
C++ Dependency Management 2.0C++ Dependency Management 2.0
C++ Dependency Management 2.0
 
C++ Memory Management
C++ Memory ManagementC++ Memory Management
C++ Memory Management
 
File Pointers
File PointersFile Pointers
File Pointers
 

Semelhante a Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)

object oriented programming part inheritance.pptx
object oriented programming part inheritance.pptxobject oriented programming part inheritance.pptx
object oriented programming part inheritance.pptx
urvashipundir04
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
Adam Getchell
 
OORPT Dynamic Analysis
OORPT Dynamic AnalysisOORPT Dynamic Analysis
OORPT Dynamic Analysis
lienhard
 

Semelhante a Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi) (20)

Software Engineering Best Practices @ Nylas
Software Engineering Best Practices @ NylasSoftware Engineering Best Practices @ Nylas
Software Engineering Best Practices @ Nylas
 
Introduction Of C++
Introduction Of C++Introduction Of C++
Introduction Of C++
 
object oriented programming part inheritance.pptx
object oriented programming part inheritance.pptxobject oriented programming part inheritance.pptx
object oriented programming part inheritance.pptx
 
1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Python
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
 
Twins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingTwins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional Programming
 
Concepts In Object Oriented Programming Languages
Concepts In Object Oriented Programming LanguagesConcepts In Object Oriented Programming Languages
Concepts In Object Oriented Programming Languages
 
Object Oriented Programming Short Notes for Preperation of Exams
Object Oriented Programming Short Notes for Preperation of ExamsObject Oriented Programming Short Notes for Preperation of Exams
Object Oriented Programming Short Notes for Preperation of Exams
 
cbybalaguruswami-e-180803051831.pptx
cbybalaguruswami-e-180803051831.pptxcbybalaguruswami-e-180803051831.pptx
cbybalaguruswami-e-180803051831.pptx
 
cbybalaguruswami-e-180803051831.pptx
cbybalaguruswami-e-180803051831.pptxcbybalaguruswami-e-180803051831.pptx
cbybalaguruswami-e-180803051831.pptx
 
PRINCE PRESENTATION(1).pptx
PRINCE PRESENTATION(1).pptxPRINCE PRESENTATION(1).pptx
PRINCE PRESENTATION(1).pptx
 
Debugging
DebuggingDebugging
Debugging
 
OORPT Dynamic Analysis
OORPT Dynamic AnalysisOORPT Dynamic Analysis
OORPT Dynamic Analysis
 
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
 
Generalized Functors - Realizing Command Design Pattern in C++
Generalized Functors - Realizing Command Design Pattern in C++Generalized Functors - Realizing Command Design Pattern in C++
Generalized Functors - Realizing Command Design Pattern in C++
 
Software Engineering
Software EngineeringSoftware Engineering
Software Engineering
 
Evolution of Patterns
Evolution of PatternsEvolution of Patterns
Evolution of Patterns
 
Software development effort reduction with Co-op
Software development effort reduction with Co-opSoftware development effort reduction with Co-op
Software development effort reduction with Co-op
 
Beware of Pointers
Beware of PointersBeware of Pointers
Beware of Pointers
 

Mais de Ovidiu Farauanu (6)

Back in Business with C++
Back in Business with C++Back in Business with C++
Back in Business with C++
 
Interface Oxidation
Interface OxidationInterface Oxidation
Interface Oxidation
 
Optimization of the build times using Conan
Optimization of the build times using ConanOptimization of the build times using Conan
Optimization of the build times using Conan
 
Bind me if you can
Bind me if you canBind me if you can
Bind me if you can
 
Distributed Cache, bridging C++ to new technologies (Hazelcast)
Distributed Cache, bridging C++ to new technologies (Hazelcast)Distributed Cache, bridging C++ to new technologies (Hazelcast)
Distributed Cache, bridging C++ to new technologies (Hazelcast)
 
Monadic Computations in C++14
Monadic Computations in C++14Monadic Computations in C++14
Monadic Computations in C++14
 

Último

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 

Último (20)

%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 

Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)

  • 1. Functional Patterns For C++ Multithreading Ovidiu Farauanu
  • 2. Summary 1. Design Patterns and OOP popularity 2. Multithreading and OOP 3. Functional Design for Multithreaded programming
  • 3. A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem. It describes the problem, the solution, when to apply the solution, and its consequences. A mix of guidelines, templates and construction advice
  • 4. (1) Design Patterns - The Celebrities: GoF Some well known patterns*: ● Creational: Singleton, Factory, Builder, etc; ● Structural: Adapter, Proxy, Facade, Decorator, etc; ● Behavioural: Command, Interpreter, State, Strategy, Visitor, Observer, Mediator, etc. *They are the same in all languages like: C++, Java, C#, etc. And well known. (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) Why is this? Oh… well, all those languages are object oriented.
  • 5. (1) Design Patterns - the wrong level of abstraction? It is logical to use common strategies to solve recurring problems. In really abstract languages it is possible to formalize those strategies and put them into a library. (Peter Norvig, Paul Graham, Edgar Holleis) Patterns are not "symptoms of not having enough abstraction in your code", but are symptoms of having not enough means of abstraction in your language. A good alternative to Object Oriented Design patterns is Aspect Oriented Programming. (Java annotation, Python decorators)
  • 6. (1) Macros (not preproc.) / Templates ● You modify/upgrade/specialize/build the language, adding some code to your libraries ... ● It’s all about the macro expander? Just string replacements and not syntax aware! ● Programmable programming language (LISP family) ● Data is code and security threats (not if happens at compile time only)
  • 8. Other types of patterns: ● Architectural patterns ● Transactional patterns ● Concurrency patterns: critical zone, lock object, guarded suspension, balking, scheduler, read/write lock, producer/consumer, two step termination, double buffering, asynchronous processing, future, thread pool, double check locking, active object, monitor object, thread specific storage, leader/followers But … what about some “functional patterns”? They are not like some UML, object composition recipes, code snippets, etc. But more related to the properties of types (types theory) in the compiler’s type system. (like: transitive immutability, function purity, etc)
  • 9. (2) Systems Programming & Multithreading I used to be obsessed with Object Oriented Design Patterns, but “as an engineer I found that I have to stay pragmatic”. The reason is: Multi-threaded programming is really, really hard. (especially when not designed carefully) The problem is shared, mutable data: OOP encourages both.
  • 10. (2) Sharing + Mutation = Data Race ● Composability: OOP has been very successful because engineers solve problems by dividing them in smaller (or easier to solve) subproblems ● Objects do not compose in the presence of concurrency ● OOP-style abstractions hide sharing and mutation ● Problem: Sharing + Mutation = Data Race ● Locking: Locking itself doesn’t compose ● Multicore programming: control over mutations (incl. CPU cache inconsistencies)
  • 11. Why I am using “multithreading” instead of “concurrency”? Most of the talks are going something like: (a) parallelism is important, so (b) let’s talk about concurrency.
  • 12. ● Concurrency is concerned with non-deterministic composition of programs ● Parallelism is concerned with asymptotic efficiency of programs with deterministic behavior Concurrency is required to implement parallelism, but it is also required to implement sequentiality too. Concurrency is not relevant to parallelism.
  • 13. (2) Concurrency is dangerous!
  • 14. (2) Concurrency and design decisions Multithreading is normally painful and must be managed with a lot of care and very good design. There are a lot of means out there to reach a safe multithreading in your software. Fact is that a lot of software at least C++ software do not use them. Florentin Picioroaga
  • 15. (2) Systems Programming I’m sorry that I long ago coined the term “objects” for this topic, because it gets many people to focus on the lesser idea. The big idea is “messaging”. -- Alan Key Concurrency is not hard (if done with proper tools), locks and threads synchronization are hard.
  • 16. Two pillars: ● Careful design of your software ● Good compiler infrastructure (or an “über” static code checker ~ formal verification?) ;
  • 17. POSA (Pattern Oriented Software Architecture) Volumes: 1 (1996), 2 (2000), 3 (2003), 4-5 (2007) Frank Buschmann, Kevlin Henney, Douglas C. Schmidt https://www.dre.vanderbilt.edu/~schmidt/POSA/
  • 18. Lock Free Synchronization ● Compare and swap ● Test and set ● Fetch and add ● Read-copy-update ● Transactional Memory (Software / Hardware in development) Require hardware support, Lock-free is not wait-free (Wait-free synchronization much harder, Usually specifiable only given a fixed number of threads); implementations of common data structures are available; Lock-free synchronization does not solve contention. Boost.Lockfree & C++11 STL?
  • 19. FP is an eternal promise FP, not a magic bullet, still have to use spinlocks, memory barriers, etc. We are systems programmers and need to use a lot of IOs, network, files, etc. → programmer must control the usage of paradigms. But what about parallel computing (multi-core programming)?
  • 20. Think function programming as “opposed” to object orientation. Function types separates data from behavior. Dijkstra: “Object-oriented programming is an exceptionally bad idea which could only have originated in California”. But he was wrong (and arogant), it actually originates in Norway (Simula in 60’s);
  • 21. Side-effects C doesn't define the order of the side effects (another reason to avoid side effects). #include <stdio .h> int foo(int n) {printf("Foo got %dn", n); return(0);} int bar(int n) {printf("Bar got %dn", n); return(0);} int main(int argc, char *argv[]) { int m = 0; int (*(fun_array[3]))(); int i = 1; int ii = i/++i; printf("ni/++i = %d, ",ii); fun_array[1] = foo; fun_array[2] = bar; (fun_array[++m])(++m); }
  • 22. (3) Immutable data and more Referential Transparency ● an expression can be replaced with its value without changing the behavior of the program ● the same results for a given set of inputs at any point in time (pure functions) This allows memoization (automatic caching) and parallelization. No side effects → functions can be evaluated in parallel trivially. (Function that “does” nothing) Advantage: Immutable sharing is never contentious ; no order dependencies Purity: a contract between functions and their callers: The implementation of a pure function does not access global mutable state.
  • 23. Transitive “const” in C++ struct A { A(): x_{ new int} {} ~A() { delete x_; } int& x() { return *x_; } const int& x() const { return *x_; } private: int* x_; }; However, it is still possible to write to *x_ from within const member functions of A. This makes it possible for const member functions to have side-effects on the class which are unexpected by the user.
  • 24. Transitive “const” in C++ C++11's smart pointers also have the property of not being transitively const pointer std::unique_ptr::get() const; typename std::add_lvalue_reference<T>::type operator*() const; pointer operator->() const; These methods all return non-const pointers and references, even if the method is called on a const std::unique_ptr instance.
  • 25. Transitive “const” in C++ template<class T, class Deleter = std::default_delete<T>> class transitive_ptr : public std::unique_ptr<T,Deleter> { public: // inherit typedefs for the sake of completeness typedef typename std::unique_ptr<T,Deleter>::pointer pointer; typedef typename std::unique_ptr<T,Deleter>::element_type element_type; typedef typename std::unique_ptr<T,Deleter>::deleter_type deleter_type; typedef const typename std::remove_pointer<pointer>::type* const_pointer; using std::unique_ptr<T,Deleter>::unique_ptr; // add transitive const version of get() pointer get() { return std::unique_ptr<T,Deleter>::get(); } const_pointer get() const { return std::unique_ptr<T,Deleter>::get(); } // add transitive const version of operator*() typename std::add_lvalue_reference<T>::type operator*() { return *get(); } typename std::add_lvalue_reference<const T>::type operator*() const { return *get(); }
  • 26. Transitive “const” in C++ // add transitive const version of operator->() pointer operator->() { return get(); } const_pointer operator->() const { return get();} };
  • 27. Function purity ● Global variables (references, location referenced pointers and static storage, incl. locals) cannot be written to ● Such variables cannot be read from, either unless they are invariant (immutable) ● Pure functions can only call other pure functions ● Parameters to a pure function can be mutable but calls cannot be cached Note: Purity is not always desirable or achievable, not a silver bullet
  • 28. Other advantages of purity ● Pure functions can be executed asynchronously. (std::async) This means that not only can the function be executed lazily (for instance using a std::promise), it can also be farmed out to another core (this will become increasingly important as more cores become commonplace). ● They can be hot swapped (meaning replaced at runtime), because they do not rely on any global initialization or termination state.
  • 29. (3) Function as object (functor) Functor - is simply any object that can be called as if it is a function, an object of a class that defines operator(). In this case function composition is similar to object composition, but with a subtle difference: behavior and data are not coupled. ⇒ Increased modularity: Because of functional purity, a part of a program cannot mess with another. → Easy refactoring
  • 30. (3) Composition // C++14 #include <utility> template<typename G, typename F> auto operator*(G&& g, F&& f) { return [g,f](auto&& t) { return g(f(std::forward<decltype(t)>(t))); }; } // Usage sample auto const f = [](int v) { return v - 1.f; }; auto const g = [](float v) { return static_cast<int>(v); }; auto const h = g * f; int main(int argc, const char* argv[]) { return h(1); }
  • 31. (3) Applicative / Concatenative This is the basic reason Unix pipes are so powerful: they form a rudimentary string-based concatenative programming language. Lazy evaluation: offers iterators that never invalidate (a problem that occurs when traversing shared mutable containers).
  • 32. The type of a concatenative function is formulated so that it takes any number of inputs, uses only the topmost of these, and returns the unused input followed by actual output. These functions are essentially operating on a list-like data structure, one that allows removal and insertion only at one end. And any programmer worth his salt can tell you what that structure is called…. A STACK
  • 33. Partial application using namespace std; using namespace std::placeholders; template<typename T> T add(T left, T right) { return left + right; } int main() { auto bound_function = std::bind(add<int>, _1, 6); // Here _1 is a placeholder } Problem: neither the compiler nor the runtime will ever complain!
  • 34. template<typename T, typename X, typename Y> auto cancel(T func, X left, Y right)->function<decltype(func(left, right))(X)> { return bind(func, left, _1); } int main() { auto bound_function = cancel(add<int>, 6, 11); cout << bound_function(22) << endl; } // bind generates a forwarding call wrapper for f. // Calling this wrapper is equivalent to invoking f with some of its arguments bound to args. // Side effects can be “ignored” or “denied” via partial application ...
  • 35. First class citizens ● Functions as parameters ● Functions as return values
  • 36. Memoization & Thunking Memoization is an old term, which often means tabling a function's result. Probably, no modern compiler does that because it's extremely expensive?? Lambda lifting: an expression containing a free variable is replaced by a function applied to that variable. (similar to “move field” refactoring operation on OOP designs) Monadic lifting...
  • 37. (3) Types are functions, not classes Typedefs of pointer to functions? How do you define a “callback” in Java? An interface with a single method, and a class that implements that interface.
  • 38. Suspenders template<class T> class Susp { public: explicit Susp(std::function<T()> f) : _f(f) {} T get() { return _f(); } private: std::function<T()> _f; }; int x = 2; int y = 3; Susp<int> sum([x, y]() { return x + y; }); ... int z = sum.get(); ● If the function is not pure, we may get different values each time; ● if the function has side effects, these may happen multiple times; ● if the function is expensive, the performance will suffer. All these problems may be addressed by memoizing the value.
  • 39. I would like it to be simple, something like: auto CounterFactory = [](int j) { auto i = j; return [i]() { i++; return i; }; };
  • 40. Thanks to ... ● Andrei Alexandrescu & Walter Bright (D and C++) ● Bartosz Milewski (Haskell and C++, D devel.) ● Scott Wlaschin ( ) ● Also thanks to Rust and Go communities