SlideShare a Scribd company logo
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

More Related Content

PDF
Cap'n Proto (C++ Developer Meetup Iasi)
PDF
Basic constructs i
PDF
FregeDay: Roadmap for resolving differences between Haskell and Frege (Ingo W...
PDF
(3) cpp procedural programming
PDF
Not Your Fathers C - C Application Development In 2016
PDF
Ruxmon.2013-08.-.CodeBro!
PDF
Algorithm and Programming (Looping Structure)
ODP
Introduction to Go for Java Developers
Cap'n Proto (C++ Developer Meetup Iasi)
Basic constructs i
FregeDay: Roadmap for resolving differences between Haskell and Frege (Ingo W...
(3) cpp procedural programming
Not Your Fathers C - C Application Development In 2016
Ruxmon.2013-08.-.CodeBro!
Algorithm and Programming (Looping Structure)
Introduction to Go for Java Developers

What's hot (20)

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

Viewers also liked (20)

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

Similar to Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi) (20)

PDF
Software Engineering Best Practices @ Nylas
PPTX
Introduction Of C++
PPTX
object oriented programming part inheritance.pptx
DOC
1183 c-interview-questions-and-answers
ODP
Patterns in Python
 
PPT
An Overview Of Python With Functional Programming
PPTX
object oriented programming language in c++
PDF
Twins: Object Oriented Programming and Functional Programming
PPT
Concepts In Object Oriented Programming Languages
PDF
Object Oriented Programming Short Notes for Preperation of Exams
PPTX
cbybalaguruswami-e-180803051831.pptx
PPTX
cbybalaguruswami-e-180803051831.pptx
PPTX
PRINCE PRESENTATION(1).pptx
ODP
Debugging
PPTX
program fundamentals using python1 2 3 4.pptx
PDF
OORPT Dynamic Analysis
PDF
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
PPT
Generalized Functors - Realizing Command Design Pattern in C++
PDF
Software Engineering
PPTX
Evolution of Patterns
Software Engineering Best Practices @ Nylas
Introduction Of C++
object oriented programming part inheritance.pptx
1183 c-interview-questions-and-answers
Patterns in Python
 
An Overview Of Python With Functional Programming
object oriented programming language in c++
Twins: Object Oriented Programming and Functional Programming
Concepts In Object Oriented Programming Languages
Object Oriented Programming Short Notes for Preperation of Exams
cbybalaguruswami-e-180803051831.pptx
cbybalaguruswami-e-180803051831.pptx
PRINCE PRESENTATION(1).pptx
Debugging
program fundamentals using python1 2 3 4.pptx
OORPT Dynamic Analysis
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
Generalized Functors - Realizing Command Design Pattern in C++
Software Engineering
Evolution of Patterns

More from Ovidiu Farauanu (9)

PDF
SIMD with C++ 26 by Alexandru Pentilescu
PDF
Introduction to C++20 Coroutines by Alex P
PDF
Interfacing C++ with Python to boost your legacy apps with Python interfaces
PDF
Back in Business with C++
PDF
Interface Oxidation
PDF
Optimization of the build times using Conan
PDF
Bind me if you can
PDF
Distributed Cache, bridging C++ to new technologies (Hazelcast)
PPTX
Monadic Computations in C++14
SIMD with C++ 26 by Alexandru Pentilescu
Introduction to C++20 Coroutines by Alex P
Interfacing C++ with Python to boost your legacy apps with Python interfaces
Back in Business with C++
Interface Oxidation
Optimization of the build times using Conan
Bind me if you can
Distributed Cache, bridging C++ to new technologies (Hazelcast)
Monadic Computations in C++14

Recently uploaded (20)

PDF
Nekopoi APK 2025 free lastest update
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
top salesforce developer skills in 2025.pdf
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PPT
Introduction Database Management System for Course Database
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Odoo POS Development Services by CandidRoot Solutions
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Nekopoi APK 2025 free lastest update
Navsoft: AI-Powered Business Solutions & Custom Software Development
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
top salesforce developer skills in 2025.pdf
Upgrade and Innovation Strategies for SAP ERP Customers
PTS Company Brochure 2025 (1).pdf.......
Internet Downloader Manager (IDM) Crack 6.42 Build 41
How to Migrate SBCGlobal Email to Yahoo Easily
2025 Textile ERP Trends: SAP, Odoo & Oracle
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Introduction Database Management System for Course Database
How to Choose the Right IT Partner for Your Business in Malaysia
ManageIQ - Sprint 268 Review - Slide Deck
Design an Analysis of Algorithms I-SECS-1021-03
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Odoo POS Development Services by CandidRoot Solutions
VVF-Customer-Presentation2025-Ver1.9.pptx
Adobe Illustrator 28.6 Crack My Vision of Vector Design

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