# C++ Threads

Nivå: advanced | Målgrupp: C++ programmerare | Förkunskaper: Stor vana att programmera i C++
https://www.ribomation.se/programmerings-kurser/cxx-threads/

Buggar i fler-trådade program anses ofta vara det besvärligaste man kan råka ut för som programmerare.
Faktum är att det generella rådet är att inte stoppa in dem från början. Om man tycker det rådet är aningen
orealistiskt, så är det näst bästa att programmera enligt ett antal väl beprövade programmerings-idiom som
undviker problemen. I denna kurs, fokuserar vi på just den strategin.

Buggar i fler-trådade program anses ofta vara det besvärligaste man kan råka ut för som programmerare.
Faktum är att det generella rådet är att inte stoppa in dem från början. Om man tycker det rådet är aningen
orealistiskt, så är det näst bästa att programmera enligt ett antal väl beprövade programmerings-idiom som
undviker problemen. I denna kurs, fokuserar vi på just den strategin.

- Program with threads in C++20 and previous versions
- Understand and deal with problem areas such as critical sections, race conditions and deadlocks
- Use mutex and conditions in both POSIX and C++
- Implement message passing
- Implement thread pools
- Understand memory management to implement private heaps for threads
- Understand and use promises/futures in C++11
- Program with POSIX Threads directly in C

### Threads

#### What is a Thread?
- Concurrent vs. parallel
- Scheduling
- Thread types
- Synchronization
- Virtual adress space organization
- Overview of how a function-call is performed and why it’s relevant to threads
- Where do all the thread lives?

#### Creating Threads
- How to create a C++20 thread
- Sample hello thread
- Explicit join
- Obtaining the current thread
- Sleeping
- How to provide the thread body
- Lambda, function, functor, method pointer
- `std::thread` vs. `std::jthread`
- `AutoJoiner` helper class for std::thread
- Passing arguments to a thread
- The problem of mixed output and how to fix it
- Moving threads
- Swapping threads
- Thread base class
- Obtain the number of processing units
- Thread local storage

#### Cooperative Interruption
- How to stop a thread
- Implicit requesting stop
- Explicit requesting stop
- Register a stop call-back
- Using a stop source/token

### Concurrency Problems

#### The Critical Section Problem
- Understanding the problem and its solution
- The ATM problem
- Account class
- ATM class
- Bank program
- Failed execution
- Critical (code) section
- What is wrong?
- Three conditions for the critical-section problem
- How to prevent the critical-section problem
- Using a mutex lock
- C++ mutex type
- Thread-safe account class
- Using a lock guard
- How to prevent self-deadlock
- Using a recursive lock
- The problem of partial mutable operations
- How to make `getBalance` const, but retain `mutex::lock`
- Using lock with time-out

#### The Race-Condition Problem
- Understanding the problem and its solution
- The SWIFT problem
- Moneybox class
- SWIFT class
- Sender thread
- Receiver thread
- Failed execution
- What is wrong?
- Condition synchronization
- C++ condition variables
- Thread-safe moneybox

#### Monitors & Capsules
- The concept monitor
- Monitor semantics
- Flexible monitor design
- Simple monitor implementation
- The concept capsule
- Simple capsule implementation

#### The Deadlock Problem
- The concept resource
- The Kitchen problem
- Resource class
- Cook thread
- Failed execution
- The Dining Philosophers problem
- Ed Coffmans conditions for deadlock
- How to handle deadlocks
- Fixing the Kitchen problem
- The Account Transfer problem
- C++ scoped locks
- Implementation of the Account Transfer problem

### More Synchronization

#### Read-Write Locks
- What is a read-write lock?
- Using a `std::shared_mutex`
- Sample demo program

#### Latches & Barriers
- What is latch?
- Latch operations
- Usage of a latch
- What is barrier?
- Barrier operations
- Usage of a barrier

#### Semaphores
- What is a semaphore?
- Counting semaphore
- C++ semaphores
- C++ binary semaphore
- Using a semaphore as a mutex
- Implementing a queue with semaphores
- Problems with semaphores
- Semaphore can be more versatile than locks
- POSIX has two types of semaphores

#### Promises & Futures
- What are promises and futures?
- C++ promises and futures
- Sample usage
- Dealing with exceptions
- Asynchronous tasks
- Usage os `std::async`
- Execution policies
- Using s shared future
- Example; scanning the file system using async tasks

### Message Queues

#### Implementation of a Thread-Safe Queue
- Logical design of a queue
- Handling queue capacity
- Implementation advice for an unbounded queue
- Class `MessageQueueUnbounded`
- Sample execution
- Implementation advice for an bounded queue
- Class `MessageQueueBounded`
- Sample execution using a bounded queue
- Dropping messages when queue full

#### Unidirectional Message Passing
- What is message-passing
- Handling pointer based messages
- Implementing interface Receivable
- Implementing a threads pipeline

#### Bidirectional Message Passing
- What is bidirectional message-passing?
- What is _rendezvous_?
- Communication patterns
- Implementation of rendezvous
- Rendezvous message class
- RPC server
- Sample client
- Execution
- Some optimizations
- Inspecting thread stack frames

#### Thread Pools
- What is a thread pool?
- The simplest thread pool implementation
- Tasks that return a result
- Task type
- The submit function
- The worker loop
- Pool creation and shutdown
- Sample test program

### Misc. Library Parts

#### Parallel STL Algorithms
- What is a parallel STL algorithm
- Parallelized algorithms
- Execution policies
- Sequenced policy
- Parallel policy
- Parallel `unsequenced` policy
- `Unsequenced` policy
- Choosing a policy
- Changes to iterator requirements
- Changes in exception behaviour
- Replaced algorithms
- Do we get any speed-ups? For which work loads?
- The benchmark program

#### Atomic Variables
- What is an atomic type/variable?
- Using `std::atomic<T>`
- Operations
- The ATM problem using an atomic int

### Under the Hood

#### POSIX Threads
- Rudimentary C API
- Creating a thread with `pthread_create`
- Passing arguments
- Thread configuration
- Setting the stack size
- PThread mutex
- The ATM problem as a C program, with pthreads
- PThread Condition
- PThread Read-Write locks
- PThread Barriers

#### Implementation of C++ Threads
- Wrapping pthreads
- Simple `thread` class
- Usage of the class
- Passing arguments
- Class `ThreadArgs`
- Usage of the modified class
- Class Mutex
- Usage of the mutex class
- Class Condition
- Usage of the condition class

### Memory Management

#### User-Defined Memory Allocation
- Limitations of using system heap for messages
- Allocation functions of the system heap
- How the system heap is implemented
- Why the heap is a large critical section
- Heap arenas in GNU glibc; multiple locks
- What is a private heap?
- Choosing storage for messages
- Possible implementation of a consumer's private heap
- Allocation strategies
- Allocation-only storage
- Monotonic allocation
- Circular allocation
- Block-pool storage

#### Understanding std::pmr
- What is a polymorphic memory resource?
- Class & function overview
- Provided memory resources
- Special-form allocators
- Usage of a `monotonic_buffer_resource`
- STL container support for std::pmr
- Usage of `unsynchronized_pool_resource`

#### Thread Private Heaps
- Basic principle for a private heap
- Sample implementation of a std::pmr based private heap
- How to organize heap storage for messages
- Sample implementation of a std::pmr based message heap

### Shared Memory

#### POSIX Processes
- What is a process?
- Understanding the system call `fork`
- Using `exit` and `wait`
- Understanding the system call `exec`
- Loading new program code

#### POSIX Shared Memory
- What is shared memory, really?
- How is it working
- Shared memory C API
- Using `mmap` to create memory segments
- Class `SharedMemory`
- Usage of the class
- Understanding the placement variant of operator `new`
- How to configure POSIX mutex and condition to work in shared memory
- Sample program; Producer-Consumer via shared memory

#### Processes with Threads & Shared Memory
- How to combine everything we discussed in this course
- Overview of the demo application
- The app part
- The Loader thread
- The Transformer thread
- The Consumer thread
- The Shared-Memory class
- The user-defined shared-memory enabled Mutex and Condition classes
- The Message-Queue class
- The Message class
- The FileSlurper class
