Skip to main content

22 docs tagged with "concurrency"

View all tags

Async and Batching

Every Runnable exposes sync and async twins (invoke/ainvoke, batch/abatch, stream/astream, from Runnables and LCEL), plus batch for running many independent inputs efficiently.

Atomics and Memory Fences

Atomic operations execute as single, indivisible steps with no interference from other threads. Memory fences (barriers) establish ordering constraints between operations.

Boost.Thread

Boost.Thread provides portable threading primitives — threads, mutexes, condition variables, futures,

C++ Memory Model

The C++ memory model defines how threads interact through memory, including visibility of writes, ordering of operations, and synchronization primitives.

Cache Coherence and MESI

How several caches holding the same line stay consistent, and why two unrelated variables in one line can destroy performance.

Condition Variables

Condition variables allow threads to wait for specific conditions to become true, enabling efficient thread coordination beyond simple mutexes.

Critical Sections and Atomicity

A bare-metal program with interrupts enabled is a concurrent program. There is one core and no scheduler, but there are still two threads of control — main and whatever handler just fired — and they share memory. Everything that makes concurrency hard is already present:atomic you can assume is lock-free, no kernel to block against.

Data Races and Race Conditions

A data race occurs when two or more threads access the same memory location concurrently, at least one access is a write, and there's no synchronization between them. Data races cause undefined behavior.

Deferred Work

"Keep your ISRs short" is the most repeated piece of firmware advice and the least actionable, because it never says short compared to what. The useful form is a consequence of how the NVIC works rather than a style preference: every microsecond a handler runs is a microsecond added to the worst-case latency of every interrupt at the same or a less urgent priority. A 200 µs handler is not "a bit slow". It is a 200 µs latency tax levied on most of the system, paid every time that handler runs, and it does not appear in any register you can read.

Futures and Promises

Futures and promises provide a mechanism for asynchronous computation: one thread computes a value and another retrieves it later.

Mutexes and Locks

A mutex (mutual exclusion) is a synchronization primitive that protects shared data by allowing only one thread to access it at a time.

Queues and Message Passing

A queue looks like a data structure and is really a design decision. The structure part is unremarkable — a circular buffer with a head, a tail and two waiting lists. The decision is what makes it worth a page: a FreeRTOS queue copies the item in and copies it out again, and every property people value in queues follows from that one fact.

Semaphores and Mutexes

Adding a scheduler adds a second way for code to be interrupted. On bare metal the only thing that could run between your load and your store was an exception handler, and Critical Sections and Atomicity is the complete answer to that. Under a kernel, a task can also be pre-empted by another task, at any instruction, for reasons that have nothing to do with the NVIC. Masking interrupts no longer covers the hazard, because the thing that pre-empted you was the scheduler doing its job.

Shared Data and Race Conditions

A single-core MCU with interrupts enabled runs a concurrent program, and the reason people are surprised by that is that the concurrency is invisible in the source. There is one main, one call stack in view, no threads to create, and nothing that looks like it could run at the same time as anything else. But between any two machine instructions the hardware may insert an entire function of someone else's code, and if that function touches a variable you were half-way through updating, the update is lost — or worse, the value it reads is one that never existed.

Task Notifications and Event Groups

Queues, semaphores, mutexes and event groups are all objects. Each has its own allocation, its own handle, and its own place in the system's RAM budget, and a sender has to be given that handle before it can say anything. The kernel's own header states the distinction plainly: those four are "intermediary objects" for sending an event, and a task notification "is a method of sending an event directly to a task without the need for such an intermediary object."

Thread Management

Threads allow programs to perform multiple operations concurrently. C++11 introduced std::thread for portable threading.

Thread Pools

A thread pool manages a fixed set of worker threads that execute tasks from a queue, avoiding the overhead of creating and destroying threads repeatedly.