@cubis/foundry 0.3.71 → 0.3.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/cli/core.js +4 -18
- package/dist/cli/core.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/core.ts +4 -18
- package/workflows/powers/accessibility/POWER.md +83 -94
- package/workflows/powers/accessibility/SKILL.md +82 -94
- package/workflows/powers/agent-design/POWER.md +201 -0
- package/workflows/powers/agent-design/SKILL.md +198 -0
- package/workflows/powers/agent-design/references/clarification-patterns.md +153 -0
- package/workflows/powers/agent-design/references/skill-testing.md +164 -0
- package/workflows/powers/agent-design/references/workflow-patterns.md +226 -0
- package/workflows/powers/agentic-eval/POWER.md +62 -0
- package/workflows/powers/agentic-eval/SKILL.md +59 -0
- package/workflows/powers/agentic-eval/references/rubric-and-regression-checklist.md +11 -0
- package/workflows/powers/api-designer/POWER.md +43 -71
- package/workflows/powers/api-designer/SKILL.md +43 -71
- package/workflows/powers/api-patterns/POWER.md +42 -56
- package/workflows/powers/api-patterns/SKILL.md +42 -57
- package/workflows/powers/architecture-designer/POWER.md +43 -60
- package/workflows/powers/architecture-designer/SKILL.md +43 -60
- package/workflows/powers/ask-questions-if-underspecified/POWER.md +51 -3
- package/workflows/powers/auth-architect/POWER.md +69 -0
- package/workflows/powers/auth-architect/SKILL.md +66 -0
- package/workflows/powers/auth-architect/references/session-token-policy-checklist.md +45 -0
- package/workflows/powers/behavioral-modes/POWER.md +100 -9
- package/workflows/powers/c-pro/POWER.md +105 -0
- package/workflows/powers/c-pro/SKILL.md +102 -0
- package/workflows/powers/c-pro/references/build-systems-and-toolchains.md +148 -0
- package/workflows/powers/c-pro/references/common-ub-and-portability.md +166 -0
- package/workflows/powers/c-pro/references/debugging-with-sanitizers.md +205 -0
- package/workflows/powers/c-pro/references/memory-safety-and-build-checklist.md +60 -0
- package/workflows/powers/c-pro/references/posix-and-platform-apis.md +244 -0
- package/workflows/powers/changelog-generator/POWER.md +127 -63
- package/workflows/powers/changelog-generator/SKILL.md +126 -63
- package/workflows/powers/ci-cd-pipelines/POWER.md +156 -0
- package/workflows/powers/ci-cd-pipelines/SKILL.md +153 -0
- package/workflows/powers/ci-cd-pipelines/references/github-actions-patterns.md +160 -0
- package/workflows/powers/ci-cd-pipelines/references/pipeline-security-checklist.md +57 -0
- package/workflows/powers/cli-developer/POWER.md +152 -95
- package/workflows/powers/cli-developer/SKILL.md +152 -95
- package/workflows/powers/cpp-pro/POWER.md +111 -0
- package/workflows/powers/cpp-pro/SKILL.md +108 -0
- package/workflows/powers/cpp-pro/references/concurrency-primitives.md +266 -0
- package/workflows/powers/cpp-pro/references/move-semantics-and-value-types.md +149 -0
- package/workflows/powers/cpp-pro/references/performance-and-profiling.md +191 -0
- package/workflows/powers/cpp-pro/references/raii-and-modern-cpp-checklist.md +87 -0
- package/workflows/powers/cpp-pro/references/template-and-concepts-patterns.md +205 -0
- package/workflows/powers/csharp-pro/POWER.md +47 -22
- package/workflows/powers/csharp-pro/SKILL.md +47 -22
- package/workflows/powers/dart-pro/POWER.md +68 -0
- package/workflows/powers/dart-pro/SKILL.md +65 -0
- package/workflows/powers/dart-pro/references/isolate-and-concurrency.md +180 -0
- package/workflows/powers/dart-pro/references/null-safety-and-async-patterns.md +133 -0
- package/workflows/powers/dart-pro/references/package-structure-and-linting.md +193 -0
- package/workflows/powers/dart-pro/references/sealed-records-patterns.md +173 -0
- package/workflows/powers/dart-pro/references/testing-and-mocking.md +235 -0
- package/workflows/powers/database-design/POWER.md +47 -33
- package/workflows/powers/database-design/SKILL.md +47 -33
- package/workflows/powers/database-optimizer/POWER.md +43 -64
- package/workflows/powers/database-optimizer/SKILL.md +43 -64
- package/workflows/powers/database-skills/POWER.md +59 -93
- package/workflows/powers/database-skills/SKILL.md +59 -93
- package/workflows/powers/debugging-strategies/POWER.md +69 -0
- package/workflows/powers/debugging-strategies/SKILL.md +66 -0
- package/workflows/powers/debugging-strategies/references/reproduce-isolate-verify-checklist.md +42 -0
- package/workflows/powers/deep-research/POWER.md +67 -0
- package/workflows/powers/deep-research/SKILL.md +64 -0
- package/workflows/powers/deep-research/references/multi-round-research-loop.md +80 -0
- package/workflows/powers/design-system-builder/POWER.md +130 -116
- package/workflows/powers/design-system-builder/SKILL.md +130 -116
- package/workflows/powers/devops-engineer/POWER.md +120 -57
- package/workflows/powers/devops-engineer/SKILL.md +120 -57
- package/workflows/powers/docker-kubernetes/POWER.md +94 -0
- package/workflows/powers/docker-kubernetes/SKILL.md +91 -0
- package/workflows/powers/docker-kubernetes/references/dockerfile-optimization-checklist.md +35 -0
- package/workflows/powers/docker-kubernetes/references/kubernetes-deployment-patterns.md +59 -0
- package/workflows/powers/documentation-templates/POWER.md +158 -127
- package/workflows/powers/documentation-templates/SKILL.md +158 -127
- package/workflows/powers/drizzle-expert/POWER.md +66 -0
- package/workflows/powers/drizzle-expert/SKILL.md +63 -0
- package/workflows/powers/drizzle-expert/references/runtime-pairing-matrix.md +16 -0
- package/workflows/powers/drizzle-expert/references/schema-and-migration-playbook.md +18 -0
- package/workflows/powers/error-ux-observability/POWER.md +144 -131
- package/workflows/powers/error-ux-observability/SKILL.md +143 -131
- package/workflows/powers/fastapi-expert/POWER.md +46 -60
- package/workflows/powers/fastapi-expert/SKILL.md +46 -60
- package/workflows/powers/firebase/POWER.md +65 -0
- package/workflows/powers/firebase/SKILL.md +62 -0
- package/workflows/powers/firebase/references/platform-routing.md +16 -0
- package/workflows/powers/firebase/references/rules-and-indexes-checklist.md +11 -0
- package/workflows/powers/flutter-design-system/POWER.md +63 -0
- package/workflows/powers/flutter-design-system/SKILL.md +60 -0
- package/workflows/powers/flutter-design-system/references/shared-widgets.md +29 -0
- package/workflows/powers/flutter-design-system/references/tokens-and-theme.md +34 -0
- package/workflows/powers/flutter-drift/POWER.md +65 -0
- package/workflows/powers/flutter-drift/SKILL.md +62 -0
- package/workflows/powers/flutter-drift/references/migrations.md +22 -0
- package/workflows/powers/flutter-drift/references/query-patterns.md +26 -0
- package/workflows/powers/flutter-feature/POWER.md +65 -0
- package/workflows/powers/flutter-feature/SKILL.md +62 -0
- package/workflows/powers/flutter-feature/references/architecture-rules.md +85 -0
- package/workflows/powers/flutter-feature/references/composite-provider.md +58 -0
- package/workflows/powers/flutter-feature/references/outbox-pattern.md +87 -0
- package/workflows/powers/flutter-feature/references/testing-patterns.md +218 -0
- package/workflows/powers/flutter-go-router/POWER.md +64 -0
- package/workflows/powers/flutter-go-router/SKILL.md +61 -0
- package/workflows/powers/flutter-go-router/references/guards-and-deeplinks.md +20 -0
- package/workflows/powers/flutter-go-router/references/typed-routes.md +27 -0
- package/workflows/powers/flutter-offline-sync/POWER.md +62 -0
- package/workflows/powers/flutter-offline-sync/SKILL.md +59 -0
- package/workflows/powers/flutter-offline-sync/references/outbox-full.md +44 -0
- package/workflows/powers/flutter-repository/POWER.md +64 -0
- package/workflows/powers/flutter-repository/SKILL.md +61 -0
- package/workflows/powers/flutter-repository/references/drift-patterns.md +21 -0
- package/workflows/powers/flutter-repository/references/retrofit-patterns.md +20 -0
- package/workflows/powers/flutter-riverpod/POWER.md +70 -0
- package/workflows/powers/flutter-riverpod/SKILL.md +67 -0
- package/workflows/powers/flutter-riverpod/references/async-and-mutations.md +19 -0
- package/workflows/powers/flutter-riverpod/references/async-lifecycle.md +19 -0
- package/workflows/powers/flutter-riverpod/references/provider-selection.md +20 -0
- package/workflows/powers/flutter-riverpod/references/testing.md +21 -0
- package/workflows/powers/flutter-riverpod/references/version-matrix.md +24 -0
- package/workflows/powers/flutter-state-machine/POWER.md +62 -0
- package/workflows/powers/flutter-state-machine/SKILL.md +59 -0
- package/workflows/powers/flutter-state-machine/references/app-state-contract.md +23 -0
- package/workflows/powers/flutter-state-machine/references/ui-rendering.md +14 -0
- package/workflows/powers/flutter-testing/POWER.md +64 -0
- package/workflows/powers/flutter-testing/SKILL.md +61 -0
- package/workflows/powers/flutter-testing/references/offline-sync-tests.md +16 -0
- package/workflows/powers/flutter-testing/references/test-layers.md +33 -0
- package/workflows/powers/frontend-code-review/POWER.md +137 -0
- package/workflows/powers/frontend-code-review/SKILL.md +134 -0
- package/workflows/powers/frontend-code-review/references/common-antipatterns.md +86 -0
- package/workflows/powers/frontend-code-review/references/performance-budgets.md +56 -0
- package/workflows/powers/frontend-code-review/references/review-checklists.md +47 -0
- package/workflows/powers/frontend-design/POWER.md +163 -362
- package/workflows/powers/frontend-design/SKILL.md +163 -362
- package/workflows/powers/game-development/POWER.md +57 -140
- package/workflows/powers/game-development/SKILL.md +57 -140
- package/workflows/powers/geo-fundamentals/POWER.md +64 -126
- package/workflows/powers/geo-fundamentals/SKILL.md +64 -127
- package/workflows/powers/git-workflow/POWER.md +135 -0
- package/workflows/powers/git-workflow/SKILL.md +132 -0
- package/workflows/powers/git-workflow/references/pr-review-checklist.md +63 -0
- package/workflows/powers/golang-pro/POWER.md +46 -35
- package/workflows/powers/golang-pro/SKILL.md +46 -35
- package/workflows/powers/graphql-architect/POWER.md +44 -62
- package/workflows/powers/graphql-architect/SKILL.md +44 -62
- package/workflows/powers/i18n-localization/POWER.md +118 -103
- package/workflows/powers/i18n-localization/SKILL.md +118 -103
- package/workflows/powers/java-pro/POWER.md +47 -22
- package/workflows/powers/java-pro/SKILL.md +47 -22
- package/workflows/powers/javascript-pro/POWER.md +47 -34
- package/workflows/powers/javascript-pro/SKILL.md +47 -34
- package/workflows/powers/kotlin-pro/POWER.md +46 -23
- package/workflows/powers/kotlin-pro/SKILL.md +46 -23
- package/workflows/powers/legacy-modernizer/POWER.md +43 -60
- package/workflows/powers/legacy-modernizer/SKILL.md +43 -60
- package/workflows/powers/mcp-builder/POWER.md +65 -0
- package/workflows/powers/mcp-builder/SKILL.md +62 -0
- package/workflows/powers/mcp-builder/references/testing-and-evals.md +17 -0
- package/workflows/powers/mcp-builder/references/transport-and-tool-design.md +17 -0
- package/workflows/powers/microservices-architect/POWER.md +43 -70
- package/workflows/powers/microservices-architect/SKILL.md +43 -70
- package/workflows/powers/mobile-design/POWER.md +110 -345
- package/workflows/powers/mobile-design/SKILL.md +110 -345
- package/workflows/powers/mongodb/POWER.md +67 -0
- package/workflows/powers/mongodb/SKILL.md +64 -0
- package/workflows/powers/mongodb/references/mongodb-checklist.md +20 -0
- package/workflows/powers/mysql/POWER.md +67 -0
- package/workflows/powers/mysql/SKILL.md +64 -0
- package/workflows/powers/mysql/references/mysql-checklist.md +20 -0
- package/workflows/powers/neki/POWER.md +67 -0
- package/workflows/powers/neki/SKILL.md +64 -0
- package/workflows/powers/neki/references/neki-checklist.md +18 -0
- package/workflows/powers/nestjs-expert/POWER.md +45 -91
- package/workflows/powers/nestjs-expert/SKILL.md +45 -91
- package/workflows/powers/nextjs-developer/POWER.md +51 -44
- package/workflows/powers/nextjs-developer/SKILL.md +51 -44
- package/workflows/powers/nodejs-best-practices/POWER.md +48 -29
- package/workflows/powers/nodejs-best-practices/SKILL.md +48 -29
- package/workflows/powers/observability/POWER.md +109 -0
- package/workflows/powers/observability/SKILL.md +106 -0
- package/workflows/powers/observability/references/alerting-and-slo-checklist.md +87 -0
- package/workflows/powers/observability/references/opentelemetry-setup-guide.md +121 -0
- package/workflows/powers/openai-docs/POWER.md +61 -0
- package/workflows/powers/openai-docs/SKILL.md +58 -0
- package/workflows/powers/openai-docs/references/official-source-playbook.md +10 -0
- package/workflows/powers/performance-profiling/POWER.md +61 -114
- package/workflows/powers/performance-profiling/SKILL.md +61 -114
- package/workflows/powers/php-pro/POWER.md +116 -0
- package/workflows/powers/php-pro/SKILL.md +113 -0
- package/workflows/powers/php-pro/references/architecture-and-di.md +239 -0
- package/workflows/powers/php-pro/references/modern-php-features.md +189 -0
- package/workflows/powers/php-pro/references/performance-and-deployment.md +197 -0
- package/workflows/powers/php-pro/references/php84-strict-typing-checklist.md +161 -0
- package/workflows/powers/php-pro/references/testing-and-static-analysis.md +235 -0
- package/workflows/powers/playwright-e2e/POWER.md +85 -0
- package/workflows/powers/playwright-e2e/SKILL.md +82 -0
- package/workflows/powers/playwright-e2e/references/locator-trace-flake-checklist.md +80 -0
- package/workflows/powers/postgres/POWER.md +67 -0
- package/workflows/powers/postgres/SKILL.md +64 -0
- package/workflows/powers/postgres/references/postgres-checklist.md +20 -0
- package/workflows/powers/prompt-engineer/POWER.md +47 -30
- package/workflows/powers/prompt-engineer/SKILL.md +47 -30
- package/workflows/powers/python-pro/POWER.md +47 -36
- package/workflows/powers/python-pro/SKILL.md +47 -36
- package/workflows/powers/react-best-practices/POWER.md +56 -33
- package/workflows/powers/react-best-practices/SKILL.md +56 -33
- package/workflows/powers/react-expert/POWER.md +47 -37
- package/workflows/powers/react-expert/SKILL.md +47 -37
- package/workflows/powers/redis/POWER.md +67 -0
- package/workflows/powers/redis/SKILL.md +64 -0
- package/workflows/powers/redis/references/redis-checklist.md +19 -0
- package/workflows/powers/ruby-pro/POWER.md +118 -0
- package/workflows/powers/ruby-pro/SKILL.md +115 -0
- package/workflows/powers/ruby-pro/references/modern-ruby-features.md +189 -0
- package/workflows/powers/ruby-pro/references/object-design-patterns.md +220 -0
- package/workflows/powers/ruby-pro/references/performance-and-profiling.md +224 -0
- package/workflows/powers/ruby-pro/references/ruby-concurrency-and-testing.md +190 -0
- package/workflows/powers/ruby-pro/references/testing-and-rspec.md +236 -0
- package/workflows/powers/rust-pro/POWER.md +45 -31
- package/workflows/powers/rust-pro/SKILL.md +45 -31
- package/workflows/powers/security-engineer/POWER.md +129 -0
- package/workflows/powers/security-engineer/SKILL.md +126 -0
- package/workflows/powers/seo-fundamentals/POWER.md +59 -102
- package/workflows/powers/seo-fundamentals/SKILL.md +59 -102
- package/workflows/powers/serverless-patterns/POWER.md +171 -0
- package/workflows/powers/serverless-patterns/SKILL.md +168 -0
- package/workflows/powers/skill-creator/POWER.md +90 -0
- package/workflows/powers/skill-creator/SKILL.md +87 -0
- package/workflows/powers/skill-creator/references/platform-formats.md +181 -0
- package/workflows/powers/skill-creator/references/schemas.md +430 -0
- package/workflows/powers/spec-miner/POWER.md +49 -57
- package/workflows/powers/spec-miner/SKILL.md +49 -57
- package/workflows/powers/sqlite/POWER.md +67 -0
- package/workflows/powers/sqlite/SKILL.md +64 -0
- package/workflows/powers/sqlite/references/sqlite-checklist.md +19 -0
- package/workflows/powers/sre-engineer/POWER.md +123 -64
- package/workflows/powers/sre-engineer/SKILL.md +123 -64
- package/workflows/powers/static-analysis/POWER.md +121 -77
- package/workflows/powers/static-analysis/SKILL.md +121 -77
- package/workflows/powers/stripe-best-practices/POWER.md +140 -17
- package/workflows/powers/stripe-best-practices/SKILL.md +139 -17
- package/workflows/powers/supabase/POWER.md +67 -0
- package/workflows/powers/supabase/SKILL.md +64 -0
- package/workflows/powers/supabase/references/supabase-checklist.md +19 -0
- package/workflows/powers/swift-pro/POWER.md +118 -0
- package/workflows/powers/swift-pro/SKILL.md +115 -0
- package/workflows/powers/swift-pro/references/concurrency-patterns.md +165 -0
- package/workflows/powers/swift-pro/references/protocol-and-generics.md +172 -0
- package/workflows/powers/swift-pro/references/sendable-and-isolation.md +116 -0
- package/workflows/powers/swift-pro/references/swift-concurrency-and-protocols.md +260 -0
- package/workflows/powers/swift-pro/references/testing-and-packages.md +192 -0
- package/workflows/powers/tailwind-patterns/POWER.md +71 -240
- package/workflows/powers/tailwind-patterns/SKILL.md +71 -240
- package/workflows/powers/testing-patterns/POWER.md +155 -10
- package/workflows/powers/testing-patterns/SKILL.md +155 -10
- package/workflows/powers/typescript-pro/POWER.md +47 -38
- package/workflows/powers/typescript-pro/SKILL.md +47 -38
- package/workflows/powers/vitess/POWER.md +67 -0
- package/workflows/powers/vitess/SKILL.md +64 -0
- package/workflows/powers/vitess/references/vitess-checklist.md +19 -0
- package/workflows/powers/vulnerability-scanner/POWER.md +146 -10
- package/workflows/powers/vulnerability-scanner/SKILL.md +146 -10
- package/workflows/powers/web-perf/POWER.md +43 -170
- package/workflows/powers/web-perf/SKILL.md +43 -170
- package/workflows/powers/webapp-testing/POWER.md +43 -164
- package/workflows/powers/webapp-testing/SKILL.md +43 -164
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# Concurrency Primitives
|
|
2
|
+
|
|
3
|
+
## `std::jthread` and `std::stop_token`
|
|
4
|
+
|
|
5
|
+
```cpp
|
|
6
|
+
#include <thread>
|
|
7
|
+
#include <stop_token>
|
|
8
|
+
|
|
9
|
+
// jthread — cooperative cancellation + auto-join
|
|
10
|
+
void worker(std::stop_token stoken) {
|
|
11
|
+
while (!stoken.stop_requested()) {
|
|
12
|
+
process_next_item();
|
|
13
|
+
}
|
|
14
|
+
// Clean up when stop is requested
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
std::jthread t(worker); // starts thread
|
|
19
|
+
// ... do work ...
|
|
20
|
+
} // jthread destructor: requests stop, then joins — no leak
|
|
21
|
+
|
|
22
|
+
// Stop callback — register actions on cancellation
|
|
23
|
+
void monitored_worker(std::stop_token stoken) {
|
|
24
|
+
std::stop_callback callback(stoken, [] {
|
|
25
|
+
std::cout << "Stop requested, cleaning up...\n";
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
while (!stoken.stop_requested()) {
|
|
29
|
+
do_work();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Mutex Strategies
|
|
35
|
+
|
|
36
|
+
```cpp
|
|
37
|
+
#include <mutex>
|
|
38
|
+
#include <shared_mutex>
|
|
39
|
+
|
|
40
|
+
// scoped_lock — locks multiple mutexes without deadlock
|
|
41
|
+
std::mutex m1, m2;
|
|
42
|
+
{
|
|
43
|
+
std::scoped_lock lock(m1, m2); // deadlock-free multi-lock
|
|
44
|
+
// ... access resources protected by both mutexes
|
|
45
|
+
} // automatically unlocked
|
|
46
|
+
|
|
47
|
+
// shared_mutex — multiple readers, single writer
|
|
48
|
+
class ThreadSafeMap {
|
|
49
|
+
mutable std::shared_mutex mutex_;
|
|
50
|
+
std::unordered_map<std::string, int> data_;
|
|
51
|
+
|
|
52
|
+
public:
|
|
53
|
+
int read(const std::string& key) const {
|
|
54
|
+
std::shared_lock lock(mutex_); // concurrent reads allowed
|
|
55
|
+
auto it = data_.find(key);
|
|
56
|
+
return it != data_.end() ? it->second : 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void write(const std::string& key, int value) {
|
|
60
|
+
std::unique_lock lock(mutex_); // exclusive write access
|
|
61
|
+
data_[key] = value;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// NEVER use lock/unlock manually — always use RAII guards
|
|
66
|
+
// WRONG: m.lock(); ... m.unlock(); // exception-unsafe
|
|
67
|
+
// RIGHT: std::lock_guard lock(m); or std::unique_lock lock(m);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Atomic Operations
|
|
71
|
+
|
|
72
|
+
```cpp
|
|
73
|
+
#include <atomic>
|
|
74
|
+
|
|
75
|
+
// Lock-free counters and flags
|
|
76
|
+
class Stats {
|
|
77
|
+
std::atomic<uint64_t> requests_{0};
|
|
78
|
+
std::atomic<uint64_t> errors_{0};
|
|
79
|
+
std::atomic<bool> healthy_{true};
|
|
80
|
+
|
|
81
|
+
public:
|
|
82
|
+
void record_request() {
|
|
83
|
+
requests_.fetch_add(1, std::memory_order_relaxed);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void record_error() {
|
|
87
|
+
errors_.fetch_add(1, std::memory_order_relaxed);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
uint64_t requests() const {
|
|
91
|
+
return requests_.load(std::memory_order_relaxed);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Memory ordering guide
|
|
96
|
+
// relaxed: no ordering guarantees, fastest — counters, flags
|
|
97
|
+
// acquire: reads see writes that happened before the matching release
|
|
98
|
+
// release: writes are visible to subsequent acquire loads
|
|
99
|
+
// seq_cst: total order across all threads — default, safest, slowest
|
|
100
|
+
|
|
101
|
+
// Compare-and-swap for lock-free data structures
|
|
102
|
+
std::atomic<Node*> head{nullptr};
|
|
103
|
+
|
|
104
|
+
void push(Node* node) {
|
|
105
|
+
node->next = head.load(std::memory_order_relaxed);
|
|
106
|
+
while (!head.compare_exchange_weak(
|
|
107
|
+
node->next, node,
|
|
108
|
+
std::memory_order_release,
|
|
109
|
+
std::memory_order_relaxed)) {
|
|
110
|
+
// retry if another thread modified head
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Condition Variables
|
|
116
|
+
|
|
117
|
+
```cpp
|
|
118
|
+
#include <condition_variable>
|
|
119
|
+
|
|
120
|
+
class BoundedQueue {
|
|
121
|
+
std::queue<int> queue_;
|
|
122
|
+
std::mutex mutex_;
|
|
123
|
+
std::condition_variable not_empty_;
|
|
124
|
+
std::condition_variable not_full_;
|
|
125
|
+
size_t max_size_;
|
|
126
|
+
|
|
127
|
+
public:
|
|
128
|
+
explicit BoundedQueue(size_t max) : max_size_(max) {}
|
|
129
|
+
|
|
130
|
+
void push(int value) {
|
|
131
|
+
std::unique_lock lock(mutex_);
|
|
132
|
+
not_full_.wait(lock, [this] { return queue_.size() < max_size_; });
|
|
133
|
+
queue_.push(value);
|
|
134
|
+
not_empty_.notify_one();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
int pop() {
|
|
138
|
+
std::unique_lock lock(mutex_);
|
|
139
|
+
not_empty_.wait(lock, [this] { return !queue_.empty(); });
|
|
140
|
+
int value = queue_.front();
|
|
141
|
+
queue_.pop();
|
|
142
|
+
not_full_.notify_one();
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## `std::latch` and `std::barrier` (C++20)
|
|
149
|
+
|
|
150
|
+
```cpp
|
|
151
|
+
#include <latch>
|
|
152
|
+
#include <barrier>
|
|
153
|
+
|
|
154
|
+
// Latch — one-time synchronization point
|
|
155
|
+
void parallel_init(size_t num_workers) {
|
|
156
|
+
std::latch ready(num_workers);
|
|
157
|
+
|
|
158
|
+
auto worker = [&ready](int id) {
|
|
159
|
+
initialize(id);
|
|
160
|
+
ready.count_down(); // signal ready
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
std::vector<std::jthread> threads;
|
|
164
|
+
for (size_t i = 0; i < num_workers; ++i) {
|
|
165
|
+
threads.emplace_back(worker, i);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
ready.wait(); // wait until all workers initialized
|
|
169
|
+
start_processing();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Barrier — reusable synchronization point
|
|
173
|
+
void iterative_computation(size_t workers, size_t iterations) {
|
|
174
|
+
std::barrier sync(workers, [] noexcept {
|
|
175
|
+
// completion function — runs once per phase after all arrive
|
|
176
|
+
merge_results();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
auto worker = [&sync, iterations](int id) {
|
|
180
|
+
for (size_t i = 0; i < iterations; ++i) {
|
|
181
|
+
compute_partial(id);
|
|
182
|
+
sync.arrive_and_wait(); // sync between iterations
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Async and Futures
|
|
189
|
+
|
|
190
|
+
```cpp
|
|
191
|
+
#include <future>
|
|
192
|
+
|
|
193
|
+
// std::async for fire-and-forget computation
|
|
194
|
+
auto future = std::async(std::launch::async, [] {
|
|
195
|
+
return expensive_computation();
|
|
196
|
+
});
|
|
197
|
+
// ... do other work ...
|
|
198
|
+
auto result = future.get(); // blocks until ready
|
|
199
|
+
|
|
200
|
+
// packaged_task for deferred execution
|
|
201
|
+
std::packaged_task<int(int)> task([](int x) { return x * x; });
|
|
202
|
+
auto future = task.get_future();
|
|
203
|
+
std::jthread t(std::move(task), 42); // execute in thread
|
|
204
|
+
int result = future.get();
|
|
205
|
+
|
|
206
|
+
// std::promise for hand-off between threads
|
|
207
|
+
std::promise<int> promise;
|
|
208
|
+
auto future = promise.get_future();
|
|
209
|
+
|
|
210
|
+
std::jthread t([&promise] {
|
|
211
|
+
try {
|
|
212
|
+
int result = compute();
|
|
213
|
+
promise.set_value(result);
|
|
214
|
+
} catch (...) {
|
|
215
|
+
promise.set_exception(std::current_exception());
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
int result = future.get(); // may throw if set_exception was called
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## C++20 Coroutines Basics
|
|
223
|
+
|
|
224
|
+
```cpp
|
|
225
|
+
#include <coroutine>
|
|
226
|
+
|
|
227
|
+
// Generator coroutine
|
|
228
|
+
template<typename T>
|
|
229
|
+
struct Generator {
|
|
230
|
+
struct promise_type {
|
|
231
|
+
T current_value;
|
|
232
|
+
auto yield_value(T value) {
|
|
233
|
+
current_value = value;
|
|
234
|
+
return std::suspend_always{};
|
|
235
|
+
}
|
|
236
|
+
Generator get_return_object() {
|
|
237
|
+
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
|
|
238
|
+
}
|
|
239
|
+
auto initial_suspend() { return std::suspend_always{}; }
|
|
240
|
+
auto final_suspend() noexcept { return std::suspend_always{}; }
|
|
241
|
+
void return_void() {}
|
|
242
|
+
void unhandled_exception() { throw; }
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
std::coroutine_handle<promise_type> handle_;
|
|
246
|
+
|
|
247
|
+
bool next() {
|
|
248
|
+
handle_.resume();
|
|
249
|
+
return !handle_.done();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
T value() const { return handle_.promise().current_value; }
|
|
253
|
+
~Generator() { if (handle_) handle_.destroy(); }
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// Usage
|
|
257
|
+
Generator<int> fibonacci() {
|
|
258
|
+
int a = 0, b = 1;
|
|
259
|
+
while (true) {
|
|
260
|
+
co_yield a;
|
|
261
|
+
auto next = a + b;
|
|
262
|
+
a = b;
|
|
263
|
+
b = next;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Move Semantics and Value Types
|
|
2
|
+
|
|
3
|
+
## Move Constructor and Assignment
|
|
4
|
+
|
|
5
|
+
```cpp
|
|
6
|
+
class Buffer {
|
|
7
|
+
std::unique_ptr<uint8_t[]> data_;
|
|
8
|
+
size_t size_;
|
|
9
|
+
|
|
10
|
+
public:
|
|
11
|
+
// Move constructor — steal resources
|
|
12
|
+
Buffer(Buffer&& other) noexcept
|
|
13
|
+
: data_(std::move(other.data_))
|
|
14
|
+
, size_(std::exchange(other.size_, 0)) {}
|
|
15
|
+
|
|
16
|
+
// Move assignment — release current, steal from other
|
|
17
|
+
Buffer& operator=(Buffer&& other) noexcept {
|
|
18
|
+
if (this != &other) {
|
|
19
|
+
data_ = std::move(other.data_);
|
|
20
|
+
size_ = std::exchange(other.size_, 0);
|
|
21
|
+
}
|
|
22
|
+
return *this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Rule of Five: if you define move ops, define or delete all five
|
|
26
|
+
Buffer(const Buffer&) = delete; // expensive copy not needed
|
|
27
|
+
Buffer& operator=(const Buffer&) = delete;
|
|
28
|
+
~Buffer() = default;
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## When to `std::move`
|
|
33
|
+
|
|
34
|
+
```cpp
|
|
35
|
+
// MOVE when transferring ownership
|
|
36
|
+
void process(std::vector<int> data) { /* owns data */ }
|
|
37
|
+
std::vector<int> v = {1, 2, 3};
|
|
38
|
+
process(std::move(v)); // v is now in moved-from state
|
|
39
|
+
|
|
40
|
+
// DO NOT move from const objects — silently copies instead
|
|
41
|
+
const std::string s = "hello";
|
|
42
|
+
std::string t = std::move(s); // copies! const prevents move
|
|
43
|
+
|
|
44
|
+
// DO NOT move return values — defeats copy elision (NRVO)
|
|
45
|
+
std::string make_string() {
|
|
46
|
+
std::string result = "hello";
|
|
47
|
+
return result; // GOOD: NRVO applies
|
|
48
|
+
// return std::move(result); // BAD: prevents NRVO
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// DO NOT use after move — object is in valid but unspecified state
|
|
52
|
+
std::vector<int> v = {1, 2, 3};
|
|
53
|
+
auto w = std::move(v);
|
|
54
|
+
// v.size() — legal but unspecified
|
|
55
|
+
// v.push_back(4) — legal, v is usable again
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Perfect Forwarding
|
|
59
|
+
|
|
60
|
+
```cpp
|
|
61
|
+
// Forward arguments preserving value category (lvalue/rvalue)
|
|
62
|
+
template<typename... Args>
|
|
63
|
+
auto make_unique_wrapper(Args&&... args) {
|
|
64
|
+
return std::make_unique<Widget>(std::forward<Args>(args)...);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Forwarding reference (T&& with template deduction) vs rvalue reference
|
|
68
|
+
template<typename T>
|
|
69
|
+
void forward_ref(T&& arg) { // forwarding reference: T is deduced
|
|
70
|
+
inner(std::forward<T>(arg));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
void rvalue_ref(Widget&& arg) { // rvalue reference: type is fixed
|
|
74
|
+
inner(std::move(arg)); // use move, not forward
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Value Categories
|
|
79
|
+
|
|
80
|
+
| Category | Can take address? | Can move from? | Examples |
|
|
81
|
+
| ----------- | ----------------- | --------------------- | ------------------------------------------------- |
|
|
82
|
+
| **lvalue** | Yes | Only with `std::move` | `x`, `*p`, `a[i]`, function returning `T&` |
|
|
83
|
+
| **prvalue** | No | Yes (implicit) | `42`, `std::string("hi")`, function returning `T` |
|
|
84
|
+
| **xvalue** | Yes\* | Yes | `std::move(x)`, function returning `T&&` |
|
|
85
|
+
|
|
86
|
+
## Copy Elision (Guaranteed since C++17)
|
|
87
|
+
|
|
88
|
+
```cpp
|
|
89
|
+
// Guaranteed copy elision — no copy/move constructor call
|
|
90
|
+
Widget make_widget() {
|
|
91
|
+
return Widget(42); // prvalue: directly constructed in caller's storage
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
Widget w = make_widget(); // no copy, no move — guaranteed
|
|
95
|
+
|
|
96
|
+
// NRVO (Named Return Value Optimization) — not guaranteed but common
|
|
97
|
+
Widget make_named() {
|
|
98
|
+
Widget w(42);
|
|
99
|
+
w.configure();
|
|
100
|
+
return w; // NRVO: likely elided, but not guaranteed
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## `std::exchange` for Clean Moves
|
|
105
|
+
|
|
106
|
+
```cpp
|
|
107
|
+
// std::exchange replaces value and returns old value — ideal for moves
|
|
108
|
+
class Socket {
|
|
109
|
+
int fd_;
|
|
110
|
+
public:
|
|
111
|
+
Socket(Socket&& other) noexcept
|
|
112
|
+
: fd_(std::exchange(other.fd_, -1)) {} // steal fd, leave -1
|
|
113
|
+
|
|
114
|
+
~Socket() {
|
|
115
|
+
if (fd_ != -1) ::close(fd_);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Reference Wrappers
|
|
121
|
+
|
|
122
|
+
```cpp
|
|
123
|
+
// std::reference_wrapper for storing references in containers
|
|
124
|
+
std::vector<std::reference_wrapper<Widget>> widgets;
|
|
125
|
+
Widget w1, w2;
|
|
126
|
+
widgets.push_back(std::ref(w1));
|
|
127
|
+
widgets.push_back(std::ref(w2));
|
|
128
|
+
|
|
129
|
+
// Useful with algorithms that copy elements
|
|
130
|
+
std::sort(widgets.begin(), widgets.end(),
|
|
131
|
+
[](const Widget& a, const Widget& b) { return a.id() < b.id(); });
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Moved-From State Obligations
|
|
135
|
+
|
|
136
|
+
A moved-from object must be in a valid state that supports:
|
|
137
|
+
|
|
138
|
+
1. Destruction (destructor runs)
|
|
139
|
+
2. Assignment (can be reused)
|
|
140
|
+
|
|
141
|
+
No other guarantees are required. Standard library types guarantee "valid but unspecified" state.
|
|
142
|
+
|
|
143
|
+
```cpp
|
|
144
|
+
// GOOD — reuse after move
|
|
145
|
+
std::string s = "hello";
|
|
146
|
+
std::string t = std::move(s);
|
|
147
|
+
s = "world"; // valid: assign new value
|
|
148
|
+
s.clear(); // valid: explicit reset
|
|
149
|
+
```
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Performance and Profiling
|
|
2
|
+
|
|
3
|
+
## Profiling Workflow
|
|
4
|
+
|
|
5
|
+
1. **Measure first** — never optimize without profiling evidence.
|
|
6
|
+
2. **Identify hotspots** — focus on the 5% of code that takes 95% of time.
|
|
7
|
+
3. **Change one thing** — benchmark before and after each change.
|
|
8
|
+
4. **Verify correctness** — run tests after every optimization.
|
|
9
|
+
|
|
10
|
+
## Profiling Tools
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# perf (Linux) — sampling profiler
|
|
14
|
+
perf record -g ./myapp # record call graph
|
|
15
|
+
perf report # interactive analysis
|
|
16
|
+
perf stat ./myapp # hardware counters summary
|
|
17
|
+
|
|
18
|
+
# Google Benchmark — microbenchmarks
|
|
19
|
+
# CMakeLists.txt
|
|
20
|
+
find_package(benchmark REQUIRED)
|
|
21
|
+
add_executable(bench bench.cpp)
|
|
22
|
+
target_link_libraries(bench benchmark::benchmark)
|
|
23
|
+
|
|
24
|
+
# VTune (Intel) — detailed CPU analysis
|
|
25
|
+
vtune -collect hotspots -- ./myapp
|
|
26
|
+
vtune -collect memory-access -- ./myapp
|
|
27
|
+
|
|
28
|
+
# Instruments (macOS)
|
|
29
|
+
xcrun xctrace record --instrument "Time Profiler" --launch ./myapp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Google Benchmark Patterns
|
|
33
|
+
|
|
34
|
+
```cpp
|
|
35
|
+
#include <benchmark/benchmark.h>
|
|
36
|
+
|
|
37
|
+
static void BM_VectorPush(benchmark::State& state) {
|
|
38
|
+
for (auto _ : state) {
|
|
39
|
+
std::vector<int> v;
|
|
40
|
+
for (int i = 0; i < state.range(0); ++i) {
|
|
41
|
+
v.push_back(i);
|
|
42
|
+
}
|
|
43
|
+
benchmark::DoNotOptimize(v.data()); // prevent dead-code elimination
|
|
44
|
+
}
|
|
45
|
+
state.SetItemsProcessed(state.iterations() * state.range(0));
|
|
46
|
+
}
|
|
47
|
+
BENCHMARK(BM_VectorPush)->Range(8, 1 << 20);
|
|
48
|
+
|
|
49
|
+
static void BM_VectorReserved(benchmark::State& state) {
|
|
50
|
+
for (auto _ : state) {
|
|
51
|
+
std::vector<int> v;
|
|
52
|
+
v.reserve(state.range(0)); // pre-allocate
|
|
53
|
+
for (int i = 0; i < state.range(0); ++i) {
|
|
54
|
+
v.push_back(i);
|
|
55
|
+
}
|
|
56
|
+
benchmark::DoNotOptimize(v.data());
|
|
57
|
+
}
|
|
58
|
+
state.SetItemsProcessed(state.iterations() * state.range(0));
|
|
59
|
+
}
|
|
60
|
+
BENCHMARK(BM_VectorReserved)->Range(8, 1 << 20);
|
|
61
|
+
|
|
62
|
+
BENCHMARK_MAIN();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Cache-Friendly Data Layout
|
|
66
|
+
|
|
67
|
+
```cpp
|
|
68
|
+
// Array of Structs (AoS) — good when you access all fields together
|
|
69
|
+
struct Particle_AoS {
|
|
70
|
+
float x, y, z;
|
|
71
|
+
float vx, vy, vz;
|
|
72
|
+
float mass;
|
|
73
|
+
};
|
|
74
|
+
std::vector<Particle_AoS> particles; // each particle contiguous
|
|
75
|
+
|
|
76
|
+
// Struct of Arrays (SoA) — good when you access one field across many elements
|
|
77
|
+
struct Particles_SoA {
|
|
78
|
+
std::vector<float> x, y, z;
|
|
79
|
+
std::vector<float> vx, vy, vz;
|
|
80
|
+
std::vector<float> mass;
|
|
81
|
+
};
|
|
82
|
+
// Iterating over just x,y,z is cache-efficient — no vx,vy,vz,mass pollution
|
|
83
|
+
|
|
84
|
+
// When to use which:
|
|
85
|
+
// AoS: random access to individual particles, insertion/deletion
|
|
86
|
+
// SoA: SIMD operations on one field, physics simulation, GPU uploads
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Allocation Reduction
|
|
90
|
+
|
|
91
|
+
```cpp
|
|
92
|
+
// Avoid repeated heap allocations in hot paths
|
|
93
|
+
// BAD — allocates string each iteration
|
|
94
|
+
for (const auto& item : items) {
|
|
95
|
+
std::string key = "prefix_" + item.name(); // allocation
|
|
96
|
+
cache.lookup(key);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// GOOD — reuse string buffer
|
|
100
|
+
std::string key;
|
|
101
|
+
key.reserve(64);
|
|
102
|
+
for (const auto& item : items) {
|
|
103
|
+
key = "prefix_";
|
|
104
|
+
key += item.name(); // may reuse existing buffer
|
|
105
|
+
cache.lookup(key);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// string_view to avoid copies
|
|
109
|
+
void process(std::string_view input) { // no copy
|
|
110
|
+
auto pos = input.find(':');
|
|
111
|
+
auto key = input.substr(0, pos); // no copy — just a view
|
|
112
|
+
auto val = input.substr(pos + 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Small Buffer Optimization (SBO) — many types use it
|
|
116
|
+
// std::string: typically 15-22 chars stored inline (no heap)
|
|
117
|
+
// std::function: small callables stored inline
|
|
118
|
+
// std::any: small types stored inline
|
|
119
|
+
// pmr allocators: customize allocation strategy
|
|
120
|
+
|
|
121
|
+
// Pre-allocate containers
|
|
122
|
+
std::vector<int> v;
|
|
123
|
+
v.reserve(expected_size); // avoids repeated reallocation
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Avoiding Virtual Dispatch in Hot Paths
|
|
127
|
+
|
|
128
|
+
```cpp
|
|
129
|
+
// Virtual dispatch: ~3-5ns per call (cache miss: ~100ns)
|
|
130
|
+
// For tight loops with millions of iterations, this matters
|
|
131
|
+
|
|
132
|
+
// std::variant + std::visit — static dispatch
|
|
133
|
+
using Shape = std::variant<Circle, Rectangle, Triangle>;
|
|
134
|
+
|
|
135
|
+
double total_area(const std::vector<Shape>& shapes) {
|
|
136
|
+
double sum = 0;
|
|
137
|
+
for (const auto& s : shapes) {
|
|
138
|
+
sum += std::visit([](const auto& shape) {
|
|
139
|
+
return shape.area(); // statically dispatched
|
|
140
|
+
}, s);
|
|
141
|
+
}
|
|
142
|
+
return sum;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// CRTP for static polymorphism (see template-and-concepts-patterns.md)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Compiler Hints
|
|
149
|
+
|
|
150
|
+
```cpp
|
|
151
|
+
// [[likely]] and [[unlikely]] for branch prediction hints
|
|
152
|
+
if (result == SUCCESS) [[likely]] {
|
|
153
|
+
process(result);
|
|
154
|
+
} else [[unlikely]] {
|
|
155
|
+
handle_error(result);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// [[assume]] (C++23) — optimizer hint
|
|
159
|
+
void process(int x) {
|
|
160
|
+
[[assume(x > 0)]]; // optimizer can assume this is true
|
|
161
|
+
// ... code that benefits from knowing x > 0
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Prefetch for known access patterns
|
|
165
|
+
for (size_t i = 0; i < n; ++i) {
|
|
166
|
+
__builtin_prefetch(&data[i + 16], 0, 1); // prefetch ahead
|
|
167
|
+
process(data[i]);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Link-Time Optimization (LTO)
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Enable LTO
|
|
175
|
+
g++ -flto -O2 -o myapp *.cpp
|
|
176
|
+
clang++ -flto=thin -O2 -o myapp *.cpp # thin LTO: faster build, similar gains
|
|
177
|
+
|
|
178
|
+
# CMake
|
|
179
|
+
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Common Performance Anti-Patterns
|
|
183
|
+
|
|
184
|
+
| Anti-pattern | Cost | Fix |
|
|
185
|
+
| -------------------------------- | ------------------------- | -------------------------------------------- |
|
|
186
|
+
| `std::map` for lookup | O(log n) + cache misses | `std::unordered_map` or sorted `std::vector` |
|
|
187
|
+
| `std::list` traversal | Cache miss per node | `std::vector` or `std::deque` |
|
|
188
|
+
| `std::shared_ptr` in hot path | Atomic ref-count per copy | `unique_ptr` or raw observer pointer |
|
|
189
|
+
| String concatenation in loop | O(n²) total allocations | `std::string::reserve` + append |
|
|
190
|
+
| `virtual` dispatch in tight loop | Vtable indirection | `std::variant` + `visit` or CRTP |
|
|
191
|
+
| Exceptions for control flow | Stack unwinding cost | Error codes or `expected<T, E>` |
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# RAII and Modern C++ Checklist
|
|
2
|
+
|
|
3
|
+
## RAII ownership patterns
|
|
4
|
+
|
|
5
|
+
### Smart pointer selection
|
|
6
|
+
|
|
7
|
+
| Pattern | Type | When to use |
|
|
8
|
+
| ------------------- | -------------------- | ----------------------------------------------------------------------------- |
|
|
9
|
+
| Exclusive ownership | `std::unique_ptr<T>` | Default choice. One owner, zero overhead, move-only. |
|
|
10
|
+
| Shared ownership | `std::shared_ptr<T>` | Multiple owners with shared lifetime. Use sparingly — adds refcount overhead. |
|
|
11
|
+
| Non-owning observer | `T*` or `T&` | Borrowing without ownership. Never delete through a raw pointer. |
|
|
12
|
+
| Weak observer | `std::weak_ptr<T>` | Observing shared-owned object without preventing destruction. |
|
|
13
|
+
|
|
14
|
+
- Prefer `std::make_unique` and `std::make_shared` over raw `new`. They are exception-safe and more efficient.
|
|
15
|
+
- Use custom deleters for non-memory resources: `unique_ptr<FILE, decltype(&fclose)> f(fopen(...), fclose);`
|
|
16
|
+
|
|
17
|
+
### Rule of five / zero
|
|
18
|
+
|
|
19
|
+
- **Rule of zero**: If a class only contains RAII members (smart pointers, containers), don't write any special member functions.
|
|
20
|
+
- **Rule of five**: If you must write a destructor, also write or delete: copy constructor, copy assignment, move constructor, move assignment.
|
|
21
|
+
- Use `= default` and `= delete` explicitly. Never leave special members implicitly generated when the class manages resources.
|
|
22
|
+
|
|
23
|
+
## Value semantics
|
|
24
|
+
|
|
25
|
+
- Prefer passing by value for small types (<= 2 words) and types you need to move from.
|
|
26
|
+
- Pass large types by `const&` for reading, by `&&` for consuming.
|
|
27
|
+
- Use `std::string_view` and `std::span<T>` for non-owning views of contiguous data.
|
|
28
|
+
- Return by value — compilers apply NRVO/RVO. Avoid `std::move` on return statements in most cases.
|
|
29
|
+
|
|
30
|
+
## Move correctness
|
|
31
|
+
|
|
32
|
+
- After `std::move`, the source object is in a valid-but-unspecified state. Only assign to it or destroy it.
|
|
33
|
+
- Mark move constructors and move assignment operators `noexcept` — this enables `std::vector` to use moves on reallocation.
|
|
34
|
+
- Test that moved-from objects don't leak resources or crash when destroyed.
|
|
35
|
+
|
|
36
|
+
## Concepts and constraints (C++20/23)
|
|
37
|
+
|
|
38
|
+
```cpp
|
|
39
|
+
template<typename T>
|
|
40
|
+
concept Hashable = requires(T a) {
|
|
41
|
+
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
template<Hashable Key, typename Value>
|
|
45
|
+
class HashMap { /* ... */ };
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- Use concepts to replace SFINAE. They produce clear error messages and are readable.
|
|
49
|
+
- Define concepts in terms of required expressions, not just type traits.
|
|
50
|
+
- Combine concepts with `requires` clauses for complex constraints.
|
|
51
|
+
|
|
52
|
+
## std::variant and pattern matching
|
|
53
|
+
|
|
54
|
+
```cpp
|
|
55
|
+
using Shape = std::variant<Circle, Rectangle, Triangle>;
|
|
56
|
+
|
|
57
|
+
double area(const Shape& s) {
|
|
58
|
+
return std::visit(overloaded{
|
|
59
|
+
[](const Circle& c) { return std::numbers::pi * c.r * c.r; },
|
|
60
|
+
[](const Rectangle& r) { return r.w * r.h; },
|
|
61
|
+
[](const Triangle& t) { return 0.5 * t.base * t.height; }
|
|
62
|
+
}, s);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- Use `std::variant` over inheritance for closed type sets. Adding a new alternative causes compile errors at all visit sites.
|
|
67
|
+
- Use the `overloaded` pattern (aggregate of lambdas) for exhaustive visiting.
|
|
68
|
+
|
|
69
|
+
## std::expected (C++23)
|
|
70
|
+
|
|
71
|
+
```cpp
|
|
72
|
+
std::expected<User, Error> find_user(int id) {
|
|
73
|
+
if (auto it = db.find(id); it != db.end())
|
|
74
|
+
return *it;
|
|
75
|
+
return std::unexpected(Error::NotFound);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- Use `std::expected<T, E>` for recoverable errors in performance-sensitive paths instead of exceptions.
|
|
80
|
+
- Chain operations with `.and_then()`, `.transform()`, `.or_else()` for monadic error handling.
|
|
81
|
+
|
|
82
|
+
## Concurrency checklist
|
|
83
|
+
|
|
84
|
+
- Use `std::jthread` + `std::stop_token` for threads that need cancellation.
|
|
85
|
+
- Use `std::scoped_lock` for multi-mutex locking — prevents deadlocks from inconsistent lock order.
|
|
86
|
+
- Use `std::atomic` with `memory_order_relaxed` only when you can prove no ordering dependency exists.
|
|
87
|
+
- Run ThreadSanitizer (`-fsanitize=thread`) on all concurrent tests in CI.
|