Concurrency with Modern C++: What every professional C++ programmer should know about concurrency

This document was uploaded by one of our users. The uploader already confirmed that they had the permission to publish it. If you are author/publisher or own the copyright of this documents, please report to us by using this DMCA report form.

Simply click on the Download Book button.

Yes, Book downloads on Ebookily are 100% Free.

Sometimes the book is free on Amazon As well, so go ahead and hit "Search on Amazon"

* C++11 and C++14 have the basic building blocks for creating concurrent or parallel programs. * With C++17, we got the parallel algorithms of the Standard Template Library (STL). That means, most of the algorithms of the STL can be executed sequential, parallel, or vectorized. * The concurrency story in C++ goes on. With C++20, we got coroutines, atomic smart pointers, semaphores, and latches and barriers. * With C++23, we can hope for executors, extended futures, transactional memory, and more. This book explains the details of concurrency in modern C++ and gives you, also, nearly 200 running code examples. Therefore, you can combine the theory with the practices and get the most of it. Because this book is about concurrency, I present many pitfalls and show you how to overcome them. The book is 100 % finished, but I will update it from time to time. The next update is probably about C++23. Furthermore, I will start the chapter on lock-free data structures.

Author(s): Rainer Grimm
Edition: 1
Publisher: Lean Publishing
Year: 2022

Language: English
Commentary: Publisher PDF
Pages: 727
Tags: C++; C++20; Concurrency Programming; Multithreading; Parallel Algorithms; Memory Model; STL; Standard Template Library; Coroutines

Table of Contents
Reader Testimonials
Introduction
Conventions
Special Fonts
Special Symbols
Special Boxes
Source Code
Run the Programs
How should you read the book?
Personal Notes
Acknowledgment
About Me
My Special Circumstances
A Quick Overview
Concurrency with Modern C++
C++11 and C++14: The Foundation
Memory Model
Multithreading
C++17: Parallel Algorithms of the Standard Template Library
Execution Policy
New Algorithms
Coroutines
Case Studies
Calculating the Sum of a Vector
The Dining Philosophers Problem by Andre Adrian
Thread-Safe Initialization of a Singleton
Ongoing Optimization with CppMem
Fast Synchronization of Threads
Variations of Futures
Modification and Generalization of a Generator
Various Job Workflows
The Future: C++23
Executors
Extended futures
Transactional Memory
Task Blocks
Data-Parallel Vector Library
Patterns and Best Practices
Synchronization
Concurrent Architecture
Best Practices
Data Structures
Challenges
Time Library
CppMem
Glossary
The Details
Memory Model
Basics of the Memory Model
What is a memory location?
What happens if two threads access the same memory location?
The Contract
The Foundation
The Challenges
Atomics
Strong versus Weak Memory Model
The Atomic Flag
std::atomic
All Atomic Operations
Free Atomic Functions
std::atomic_ref (C++20)
The Synchronization and Ordering Constraints
The Six Variants of Memory Orderings in C++
Sequential Consistency
Acquire-Release Semantic
std::memory_order_consume
Relaxed Semantic
Fences
std::atomic_thread_fence
std::atomic_signal_fence
Multithreading
The Basic Thread std::thread
Thread Creation
Thread Lifetime
Thread Arguments
Member Functions
The Improved Thread std::jthread (C++20)
Automatically Joining
Cooperative Interruption of a std::jthread
Shared Data
Mutexes
Locks
std::lock
Thread-safe Initialization
Thread-Local Data
Condition Variables
The Predicate
Lost Wakeup and Spurious Wakeup
The Wait Workflow
Cooperative Interruption (C++20)
std::stop_source
std::stop_token
std::stop_callback
A General Mechanism to Send Signals
Additional Functionality of std::jthread
New wait Overloads for the condition_variable_any
Semaphores (C++20)
Latches and Barriers (C++20)
std::latch
std::barrier
Tasks
Tasks versus Threads
std::async
std::packaged_task
std::promise and std::future
std::shared_future
Exceptions
Notifications
Synchronized Outputstreams (C++20)
Parallel Algorithms of the Standard Template Library
Execution Policies
Parallel and Vectorized Execution
Exceptions
Hazards of Data Races and Deadlocks
Algorithms
The New Algorithms
More overloads
The functional Heritage
Compiler Support
Microsoft Visual Compiler
GCC Compiler
Further Implementations of the Parallel STL
Performance
Microsoft Visual Compiler
GCC Compiler
Coroutines (C++20)
A Generator Function
Characteristics
Typical Use Cases
Underlying Concepts
Design Goals
Becoming a Coroutine
The Framework
Promise Object
Coroutine Handle
Coroutine Frame
Awaitables and Awaiters
Awaitables
The Concept Awaiter
std::suspend_always and std::suspend_never
initial_suspend
final_suspend
Awaiter
The Workflows
The Promise Workflow
The Awaiter Workflow
co_return
A Future
co_yield
An Infinite Data Stream
co_await
Starting a Job on Request
Thread Synchronization
Case Studies
Calculating the Sum of a Vector
Single Threaded addition of a Vector
Multithreaded Summation with a Shared Variable
Thread-Local Summation
Summation of a Vector: The Conclusion
The Dining Philosophers Problem by Andre Adrian
Multiple Resource Use
Multiple Resource Use with Logging
Erroneous Busy Waiting without Resource Hierarchy
Erroneous Busy Waiting with Resource Hierarchy
Still Erroneous Busy Waiting with Resource Hierarchy
Correct Busy Waiting with Resource Hierarchy
Good low CPU load Busy Waiting with Resource Hierarchy
std::mutex with Resource Hierarchy
std::lock_guard with Resource Hierarchy
std::lock_guard and Synchronized Output with Resource Hierarchy
std::lock_guard and Synchronized Output with Resource Hierarchy and a count
A std::unique_lock using deferred locking
A std::scoped_lock with Resource Hierarchy
The Original Dining Philosophers Problem using Semaphores
A C++20 Compatible Semaphore
Thread-Safe Initialization of a Singleton
Double-Checked Locking Pattern
Performance Measurement
Thread-Safe Meyers Singleton
std::lock_guard
std::call_once with std::once_flag
Atomics
Performance Numbers of the various Thread-Safe Singleton Implementations
Ongoing Optimization with CppMem
CppMem: Non-Atomic Variables
CppMem: Locks
CppMem: Atomics with Sequential Consistency
CppMem: Atomics with Acquire-Release Semantic
CppMem: Atomics with Non-atomics
CppMem: Atomics with Relaxed Semantic
Conclusion
Fast Synchronization of Threads
Condition Variables
std::atomic_flag
std::atomic
Semaphores
All Numbers
Variations of Futures
A Lazy Future
Execution on Another Thread
Modification and Generalization of a Generator
Modifications
Generalization
Various Job Workflows
The Transparent Awaiter Workflow
Automatically Resuming the Awaiter
Automatically Resuming the Awaiter on a Separate Thread
The Future: C++23
Executors
A long Way
What is an Executor?
First Examples
Goals of an Executor Concept
Terminology
Execution Functions
A Prototype Implementation
Extended Futures
Concurrency TS v1
Unified Futures
Transactional Memory
ACI(D)
Synchronized and Atomic Blocks
transaction_safe versus transaction_unsafe Code
Task Blocks
Fork and Join
define_task_block versus define_task_block_restore_thread
The Interface
The Scheduler
Data-Parallel Vector Library
Data-Parallel Vectors
The Interface of the Data-Parallel Vectors
Patterns
Patterns and Best Practices
History
Invaluable Value
Pattern versus Best Practices
Anti-Pattern
Synchronization Patterns
Dealing with Sharing
Copied Value
Thread-Specific Storage
Future
Dealing with Mutation
Scoped Locking
Strategized Locking
Thread-Safe Interface
Guarded Suspension
Concurrent Architecture
Active Object
Challenges
Solution
Components
Dynamic Behavior
Advantages and Disadvantages
Implementation
Monitor Object
Challenges
Solution
Components
Dynamic Behavior
Advantages and Disadvantages
Half-Sync/Half-Async
Challenges
Solution
Components
Dynamic Behavior
Advantages and Disadvantages
Example
Reactor
Challenges
Solution
Components
Dynamic Behavior
Advantages and Disadvantages
Example
Proactor
Challenges
Solution
Components
Advantages and Disadvantages
Example
Further Information
Best Practices
General
Code Reviews
Minimize Sharing of Mutable Data
Minimize Waiting
Prefer Immutable Data
Use pure functions
Look for the Right Abstraction
Use Static Code Analysis Tools
Use Dynamic Enforcement Tools
Multithreading
Threads
Data Sharing
Condition Variables
Promises and Futures
Memory Model
Don't use volatile for synchronization
Don't program Lock Free
If you program Lock-Free, use well-established patterns
Don't build your abstraction, use guarantees of the language
Don't reinvent the wheel
Data Structures
General Considerations
Concurrent Stack
Locking Strategy
Granularity of the Interface
Typical Usage Pattern
Linux (GCC)
Windows (cl.exe)
Avoidance of Loopholes
Contention
Single-Threaded Summation without Synchronization
Single-Threaded Summation with Synchronization (lock)
Single-Threaded Summation with Synchronization (atomic)
The Comparison
Scalability
Invariants
Exceptions
Lock-Based Data Structures
A Stack
Concurrent Queue
A Queue
Coarse-Grained Locking
Fine-Grained Locking
Lock-Free Data Structures
General Considerations
The Next Evolutionary Step
Sequential Consistency
Concurrent Stack
A Simplified Implementation
A Complete Implementation
Concurrent Queue
Further Information
Challenges
ABA Problem
Blocking Issues
Breaking of Program Invariants
Data Races
Deadlocks
False Sharing
Lifetime Issues of Variables
Moving Threads
Race Conditions
The Time Library
The Interplay of Time Point, Time Duration, and Clock
Time Point
From Time Point to Calendar Time
Cross the valid Time Range
Time Duration
Calculations
Clocks
Accuracy and Steadiness
Epoch
Sleep and Wait
CppMem - An Overview
The simplified Overview
1. Model
2. Program
3. Display Relations
4. Display Layout
5. Model Predicates
The Examples
Glossary
adress_free
ACID
CAS
Callable Unit
Complexity
Concepts
Concurrency
Critical Section
Deadlock
Eager Evaluation
Executor
Function Objects
Lambda Functions
Lazy evaluation
Lock-free
Lock-based
Lost Wakeup
Math Laws
Memory Location
Memory Model
Modification Order
Monad
Non-blocking
obstruction-free
Parallelism
Predicate
Pattern
RAII
Release Sequence
Sequential Consistency
Sequence Point
Spurious Wakeup
Thread
Total order
TriviallyCopyable
Undefined Behavior
volatile
wait-free
Index