memory-model — скилл для Claude Code: порядок памяти в C++ и Rust
Скилл для работы с моделью памяти C++ и Rust: подсказывает, какой memory order выбрать, и разбирает гонки данных в атомиках.
npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a claude-codeЧто делает memory-model
Скилл включается, когда в разговоре всплывают memory ordering, acquire-release, seq_cst, relaxed-атомики, happens-before, барьеры памяти, std::atomic или Rust-атомики. Агент получает таблицу соответствия между C++ и Rust, шкалу силы ордеров от Relaxed до SeqCst и разбор того, что каждый ордер гарантирует.
Внутри — рабочий процесс из восьми шагов: обзор ордеров, таблица memory_order_* против Ordering::*, примеры на std::atomic, дерево выбора ордера под задачу, готовые паттерны (спинлок, подсчёт ссылок, ленивая инициализация), Rust-атомики, барьеры и таблица частых ошибок. Отдельно разобрано, почему volatile в C++ не годится для потокобезопасности и почему SeqCst везде — не лучший вариант.
Скилл ссылается на справочник references/cpp-memory-ordering.md и на смежные скиллы: санитайзеры для поиска гонок, Miri для проверки нарушений порядка в Rust, ассемблер x86 для разбора сгенерированных инструкций-барьеров. Ставить его стоит, если вы пишете lock-free структуры или разбираете чужой конкурентный код — на глаз такие ошибки не ловятся.
Какие задачи решает
- выбрать memory order под конкретную атомарную операцию
- разобрать, почему acquire-release не даёт нужной синхронизации
- собрать lock-free очередь с несколькими производителями
- найти гонку данных в коде на
std::atomic - перевести паттерн с C++ атомиков на Rust
Ordering
Примеры запросов агенту
- Какой memory order поставить на этот store, если я публикую данные в другой поток?
- Помоги разобрать спинлок на
std::atomic_flag— правильные ли там acquire и release - Перепиши этот счётчик ссылок с C++ на Rust-атомики, объясни выбор
Ordering
Как установить memory-model
1Через Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a claude-code2Вручную: положить файлы
~/.claude/skills/memory-model/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/memory-model/
1Через Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a codex2Вручную: положить файлы
.agents/skills/memory-model/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a cursor2Вручную: положить файлы
.cursor/skills/memory-model/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install mohitmishra786/low-level-dev-skills memory-model2Вручную: положить файлы
.github/skills/memory-model/SKILL.md1Через Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a gemini-cli2Командой платформы
gemini skills install https://github.com/mohitmishra786/low-level-dev-skills --path skills/low-level-programming/memory-modelВручную: положить файлы
.devin/skills/memory-model/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Из того же набора62
Похожие
Рядом в теме «Языки программирования»
Все скиллы по теме «Языки программирования» →Вопросы о memory-model
Как установить memory-model в Claude?
Одной командой: npx skills add mohitmishra786/low-level-dev-skills --skill memory-model -a claude-code. После неё скилл лежит в ~/.claude/skills/memory-model/SKILL.md.
Что делает memory-model?
Ведёт агента по модели памяти C++ и Rust: объясняет ордера, отношение happens-before, барьеры и паттерны lock-free структур. Активируется на вопросах про std::atomic, acquire-release, seq_cst и relaxed-атомики.
С какими скиллами он работает вместе?
С санитайзерами для отлова гонок, с Miri для проверки нарушений порядка в Rust и с ассемблером x86, если нужно посмотреть сгенерированные инструкции-барьеры.
Исходный текст
SKILL.md · MIT
---
name: memory-model
description: C++ and Rust memory model skill for concurrent programming. Use when understanding memory ordering, writing lock-free data structures, using std::atomic or Rust atomics, diagnosing data races, or selecting the correct memory order for atomic operations. Activates on queries about memory ordering, acquire-release, seq_cst, relaxed atomics, happens-before, memory barriers, std::atomic, or Rust atomic ordering.
---
# Memory Model
## Purpose
Guide agents through C++ and Rust memory models: memory orderings, the happens-before relation, atomic operations, fences, and practical patterns for lock-free data structures.
## Triggers
- "What is the C++ memory model?"
- "What memory order should I use for my atomic operation?"
- "What is the difference between acquire-release and seq_cst?"
- "How do I use std::atomic in C++?"
- "What is acquire/release in Rust atomics?"
- "How do I implement a lock-free queue?"
## Workflow
### 1. Memory ordering overview
Modern CPUs and compilers reorder operations for performance. The memory model specifies what reorderings are allowed and how synchronisation is achieved.
```text
Ordering strength (weakest to strongest):
Relaxed < Release/Acquire < AcqRel < SeqCst
Stronger ordering = more synchronization = more correct, but slower
Weaker ordering = fewer barriers = faster, but needs careful analysis
```
### 2. Memory orderings
| Order | C++ | Rust | What it means |
|-------|-----|------|--------------|
| Relaxed | `memory_order_relaxed` | `Ordering::Relaxed` | No ordering guarantee; just atomicity |
| Consume | `memory_order_consume` | (use Acquire) | Data dependency ordering |
| Acquire | `memory_order_acquire` | `Ordering::Acquire` | This load sees all writes before the matching release |
| Release | `memory_order_release` | `Ordering::Release` | All writes before this store are visible to acquire |
| AcqRel | `memory_order_acq_rel` | `Ordering::AcqRel` | Both acquire and release on RMW ops |
| SeqCst | `memory_order_seq_cst` | `Ordering::SeqCst` | Total order across all seq_cst operations |
### 3. C++ std::atomic
```cpp
#include <atomic>
#include <thread>
std::atomic<int> counter{0};
std::atomic<bool> ready{false};
// Producer thread
void producer() {
data = 42; // (1) write data
ready.store(true, std::memory_order_release); // (2) signal
}
// Consumer thread
void consumer() {
while (!ready.load(std::memory_order_acquire)); // (3) wait
assert(data == 42); // (4) guaranteed to see (1)
}
```
Acquire-release guarantees: if thread A does a **release store** to X, and thread B does an **acquire load** that sees A's value, then all writes by A before the release are visible to B after the acquire.
### 4. Choosing the right ordering
```text
Use case?
├── Counter (just needs atomicity, order irrelevant) → Relaxed
├── Reference counting (decrement + final check) → AcqRel (dec), Acquire (load 0 check)
├── Publish data from one thread to another → Release (store), Acquire (load)
├── Mutual exclusion / mutex implementation → AcqRel / SeqCst
├── Lock-free queue multiple producers/consumers → SeqCst (safest to start)
└── Sequence number check (simple flag) → Release + Acquire
```
### 5. Common patterns
```cpp
// Pattern 1: Spinlock
class Spinlock {
std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
void lock() {
while (flag.test_and_set(std::memory_order_acquire))
; // spin
}
void unlock() {
flag.clear(std::memory_order_release);
}
};
// Pattern 2: Reference counting
class RefCounted {
std::atomic<int> refcount{1};
public:
void addref() {
refcount.fetch_add(1, std::memory_order_relaxed); // only need atomicity
}
void release() {
if (refcount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
// AcqRel ensures we see all writes from other releasers
delete this;
}
}
};
// Pattern 3: One-time initialisation
class LazyInit {
std::atomic<void*> ptr{nullptr};
std::mutex mtx;
public:
void* get() {
void* p = ptr.load(std::memory_order_acquire);
if (p == nullptr) {
std::lock_guard lock(mtx);
p = ptr.load(std::memory_order_relaxed);
if (p == nullptr) {
p = create();
ptr.store(p, std::memory_order_release);
}
}
return p;
}
};
```
### 6. Rust atomics
```rust
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
// Simple counter
let counter = Arc::new(AtomicUsize::new(0));
// Increment
counter.fetch_add(1, Ordering::Relaxed);
// Read
let val = counter.load(Ordering::Relaxed);
// Publish/subscribe pattern
static READY: AtomicBool = AtomicBool::new(false);
// Publisher thread
unsafe { DATA = 42; } // Write data
READY.store(true, Ordering::Release); // Signal
// Subscriber thread
while !READY.load(Ordering::Acquire) {}
let d = unsafe { DATA }; // Safe: guaranteed to see publisher's write
```
### 7. Fences
Fences provide ordering without an atomic operation on a specific variable:
```cpp
// C++ fence — equivalent to a global memory barrier
std::atomic_thread_fence(std::memory_order_acquire); // Acquire fence
std::atomic_thread_fence(std::memory_order_release); // Release fence
// Typical use: multiple atomic writes then one fence
relaxed_atomic_a.store(1, std::memory_order_relaxed);
relaxed_atomic_b.store(2, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release); // barrier for all above
sentinel.store(true, std::memory_order_relaxed);
```
### 8. Common mistakes
| Mistake | Fix |
|---------|-----|
| Using Relaxed for publish/subscribe | Use Release on store, Acquire on load |
| Using SeqCst everywhere | Profile first; use weakest correct ordering |
| Forgetting that non-atomic loads are not atomic | All shared mutable data needs atomic or mutex |
| Using `volatile` for thread safety in C++ | `volatile` is not a memory ordering tool; use `atomic` |
| Assuming sequential consistency without SeqCst | Each platform has different default consistency |
For memory ordering rules and happens-before reference, see [references/cpp-memory-ordering.md](references/cpp-memory-ordering.md).
## Related skills
- Use `skills/runtimes/sanitizers` — TSan detects data races involving non-atomic accesses
- Use `skills/rust/rust-sanitizers-miri` for detecting Rust memory ordering violations with Miri
- Use `skills/low-level-programming/assembly-x86` to understand generated fence instructions
- Use `skills/debuggers/gdb` for debugging concurrent programs with thread inspection
© mohitmishra786 · MIT · mohitmishra786/low-level-dev-skills