Skip to content

Commit 4bbc71b

Browse files
committed
refactor(arch): architecture deepening round 3 - improve testability
Changes: - Remove duplicate SPSCQueue definition in concurrency_properties.cpp - Unify allocator naming: aligned_allocator -> AlignedAllocator (PascalCase) - Add core module tests (15 tests for cache_line_size, page_size, hardware_concurrency) - Add lock-free queue stress tests (high throughput, MPMC contention, random interleaving) - Add overflow protection to AlignedAllocator::allocate() - Fix compile_time.hpp missing #include <cstddef> - Document header-only design decision in AGENTS.md - Add teaching example note to particle_types.hpp Test count: 65 -> 84 (+19) All tests pass with Debug, ASan, TSan builds.
1 parent d2f74f9 commit 4bbc71b

13 files changed

Lines changed: 684 additions & 84 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This repository is in **closure and hardening mode** (archive-ready for low-freq
1111
- **Memory safety**: prefer RAII, smart pointers, avoid raw `new/delete`
1212
- **Performance**: always measure with benchmarks before claiming improvement
1313
- **Concurrency**: use `std::atomic` with explicit memory ordering
14+
- **Header-only design**: all library code in `include/hpc/` and `examples/*/include/` is header-only. Platform-specific code (Windows/POSIX, compiler intrinsics) is hidden behind preprocessor conditionals within headers. This design choice prioritizes ease of integration over compilation speed.
1415

1516
## Canonical sources of truth
1617

examples/02-memory-cache/include/memory_utils.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ using aligned_unique_ptr = std::unique_ptr<T, AlignedDeleter>;
8181
* @brief Create aligned unique pointer
8282
*/
8383
template <typename T>
84-
aligned_unique_ptr<T> make_aligned(std::size_t count, std::size_t alignment = hpc::core::CACHE_LINE_SIZE) {
84+
aligned_unique_ptr<T> make_aligned(std::size_t count,
85+
std::size_t alignment = hpc::core::CACHE_LINE_SIZE) {
8586
void* ptr = aligned_alloc(count * sizeof(T), alignment);
8687
if (!ptr) {
8788
throw std::bad_alloc();

examples/02-memory-cache/include/particle_types.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
* @file particle_types.hpp
33
* @brief Particle data structures for AOS vs SOA comparison
44
*
5+
* **Note: This is a teaching example module, not production-ready code.**
6+
* The data structures and algorithms here are intentionally simple to
7+
* demonstrate memory layout concepts. For production use, consider:
8+
* - Adding bounds checking and validation
9+
* - Using aligned allocators for SIMD operations
10+
* - Implementing parallel processing for large datasets
11+
*
512
* Validates:
613
* - Requirement 2.1: AOS vs SOA Comparison
714
*

examples/03-modern-cpp/include/compile_time.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#pragma once
1515

1616
#include <array>
17+
#include <cstddef>
1718
#include <cstdint>
1819

1920
namespace hpc::compile_time {

examples/03-modern-cpp/src/compile_time.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
* - Template metaprogramming vs constexpr
1313
*/
1414

15+
#include "compile_time.hpp"
16+
1517
#include <chrono>
1618
#include <cmath>
1719
#include <iostream>
1820

19-
#include "compile_time.hpp"
20-
2121
namespace hpc::compile_time {
2222

2323
//------------------------------------------------------------------------------

examples/03-modern-cpp/src/vector_reserve.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
* - Counting allocations with custom allocator
1212
*/
1313

14+
#include "vector_reserve.hpp"
15+
1416
#include <chrono>
1517
#include <iostream>
1618
#include <vector>
1719

18-
#include "vector_reserve.hpp"
19-
2020
namespace hpc::vector_reserve {
2121

2222
//------------------------------------------------------------------------------

examples/04-simd-vectorization/include/simd_utils.hpp

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <cstddef>
2222
#include <cstdint>
2323
#include <cstdlib>
24+
#include <limits>
2425
#include <memory>
2526
#include <new>
2627
#include <vector>
@@ -93,27 +94,32 @@ inline size_t get_simd_alignment() {
9394
* different purposes: SIMD optimization vs cache-line alignment.
9495
*/
9596
template <typename T>
96-
class aligned_allocator {
97+
class AlignedAllocator {
9798
public:
9899
using value_type = T;
99-
using pointer = T*;
100-
using const_pointer = const T*;
101-
using reference = T&;
102-
using const_reference = const T&;
103100
using size_type = std::size_t;
104101
using difference_type = std::ptrdiff_t;
105102

106103
template <typename U>
107104
struct rebind {
108-
using other = aligned_allocator<U>;
105+
using other = AlignedAllocator<U>;
109106
};
110107

111-
aligned_allocator() = default;
108+
AlignedAllocator() = default;
112109

113110
template <typename U>
114-
aligned_allocator(const aligned_allocator<U>&) {}
111+
AlignedAllocator(const AlignedAllocator<U>&) {}
112+
113+
T* allocate(size_type n) {
114+
// Overflow protection
115+
if (n > std::numeric_limits<size_type>::max() / sizeof(T)) {
116+
throw std::bad_alloc();
117+
}
118+
119+
if (n == 0) {
120+
return nullptr;
121+
}
115122

116-
pointer allocate(size_type n) {
117123
const size_t alignment = get_simd_alignment();
118124
const size_t size = n * sizeof(T);
119125

@@ -128,10 +134,13 @@ class aligned_allocator {
128134
if (!ptr) {
129135
throw std::bad_alloc();
130136
}
131-
return static_cast<pointer>(ptr);
137+
return static_cast<T*>(ptr);
132138
}
133139

134-
void deallocate(pointer p, size_type) {
140+
void deallocate(T* p, size_type) {
141+
if (p == nullptr) {
142+
return;
143+
}
135144
#if defined(_MSC_VER)
136145
_aligned_free(p);
137146
#else
@@ -140,37 +149,34 @@ class aligned_allocator {
140149
}
141150

142151
template <typename U>
143-
bool operator==(const aligned_allocator<U>&) const {
152+
bool operator==(const AlignedAllocator<U>&) const {
144153
return true;
145154
}
146155

147156
template <typename U>
148-
bool operator!=(const aligned_allocator<U>&) const {
157+
bool operator!=(const AlignedAllocator<U>&) const {
149158
return false;
150159
}
151160
};
152161

153162
/**
154-
* @brief Alias for aligned_allocator with clearer SIMD-specific naming
155-
*
156-
* This alias provides a more intuitive name for the SIMD-aligned allocator,
157-
* distinguishing it from hpc::memory::AlignedAllocator which uses cache-line
158-
* alignment (compile-time constant).
159-
*
160-
* Key differences from hpc::memory::AlignedAllocator:
161-
* - Uses runtime SIMD detection for alignment (16/32/64 bytes based on CPU)
162-
* - hpc::memory::AlignedAllocator uses compile-time CACHE_LINE_SIZE
163-
*
164-
* Both names (aligned_allocator and simd_allocator) are equivalent.
163+
* @brief Backward-compatible alias for AlignedAllocator
164+
* @deprecated Use AlignedAllocator<T> directly
165+
*/
166+
template <typename T>
167+
using aligned_allocator [[deprecated("Use AlignedAllocator<T> directly")]] = AlignedAllocator<T>;
168+
169+
/**
170+
* @brief Alias for AlignedAllocator with SIMD-specific naming
165171
*/
166172
template <typename T>
167-
using simd_allocator = aligned_allocator<T>;
173+
using simd_allocator = AlignedAllocator<T>;
168174

169175
/**
170176
* @brief Aligned vector type for SIMD operations
171177
*/
172178
template <typename T>
173-
using aligned_vector = std::vector<T, aligned_allocator<T>>;
179+
using aligned_vector = std::vector<T, AlignedAllocator<T>>;
174180

175181
/**
176182
* @brief Aligned buffer type alias for compatibility

0 commit comments

Comments
 (0)