Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 2 additions & 87 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,98 +18,13 @@ under *Changed* or *Removed*.
The `Unreleased` block accumulates entries during development and is rolled into a
dated version block (`## [X.Y.Z] — YYYY-MM-DD`) when a release PR closes a milestone.

### Added

- **Benchmark extension — tail-latency percentiles and optional jemalloc/tcmalloc baselines.**
The pool-vs-malloc microbenchmark gains an opt-in `--percentiles` mode that emits a separate
per-operation **p50/p90/p99/p999** table — the dynamic-pool growth row surfaces the
microsecond-scale growth spike the aggregate median hides — and **jemalloc** / **tcmalloc**
baselines measured the safe way, by re-running the bench under **`LD_PRELOAD`** (those
allocators take over global `malloc` on load, so they cannot be linked or `dlopen`'d beside
the system allocator without crashing). A `# allocator:` header line discloses which allocator
each run measured; the bench carries no allocator-specific code, so the default build stays
zero-external-dependency (spec §3.3). Both are strictly additive: the
[ADR-0014](docs/adr/0014-microbenchmark-methodology-pool-vs-malloc.md) aggregate ns/op table
and its committed numbers are unchanged. A Linux `bench-baselines` CI cell installs both
allocators and exercises the new paths (non-asserting on numbers, per ADR-0014 §8).
[ADR-0045](docs/adr/0045-benchmark-percentiles-and-external-baselines.md). Closes #111.
- **Coverage-guided fuzzing harness for the pool surface.** A new
[`pool_fuzz.cpp`](src/test/cpp/it/d4np/memorypool/pool_fuzz.cpp) drives randomized
`alloc` / `free(valid)` / `free(NULL)` / `free(foreign)` sequences — over both fixed and
dynamic-growth pools — through a stateful opcode interpreter, asserting the no-alias,
per-block-canary, foreign/NULL-no-op ([ADR-0012](docs/adr/0012-foreign-pointer-and-out-of-range-pointer-policy.md)),
and `InstrumentedPool` accounting invariants against a shadow oracle so a corruption becomes
a saved reproducer. One engine-agnostic source yields the Clang-only libFuzzer target
`pool_fuzz` (opt-in `PBR_MEMORY_POOL_BUILD_FUZZERS`; a `fuzz` preset builds it under
`-fsanitize=fuzzer,address,undefined`, and a dedicated CI job replays the seed corpus and
fuzzes for a bounded time on every PR) and an always-built standalone `pool_fuzz_replay` that
makes the seed corpus a portable regression gate everywhere — including MSVC, where libFuzzer
is unavailable. Test-only and additive; the release build and the benchmark numbers are
untouched. [ADR-0044](docs/adr/0044-coverage-guided-fuzzing-harness.md). Closes #108.
- **Opt-in debug hardening — freed-block poisoning, a guard word, and free-list
safe-linking.** A compile-time knob `PBR_MEMORY_POOL_HARDENING` (OFF by default; a `harden`
CMake preset turns it on) hardens the intrusive free list against the classic
use-after-free / pointer-corruption primitives an in-band next-link exposes: freed blocks are
**poisoned** (`0xDE`) and verified on the next allocation (use-after-free), a per-slot
trailing **guard word** detects a contiguous write past `block_size` (buffer overflow) and a
repeated free (double-free — the [ADR-0012](docs/adr/0012-foreign-pointer-and-out-of-range-pointer-policy.md)
gap), and the next-link is stored with glibc-style **safe-linking**
(`ptr XOR (slot_addr >> 12)`) so a leaked/overwritten link is neither usable nor silently
followed. On detection a swappable `HardeningViolationHandler`
([`pool_hardening.hpp`](src/main/cpp/it/d4np/memorypool/pool_hardening.hpp)) fires — the
default prints a diagnostic and `abort()`s. The guard lives in *added* slot stride, so the
user-visible `block_size` and the [ADR-0009](docs/adr/0009-free-list-layout-block-size-constraints-and-alignment-guarantee.md)
alignment guarantee are unchanged, and the default build is byte-for-byte and cycle-for-cycle
unchanged (the knob is fully compiled out). Works with fixed and dynamic pools across all
three thread-safety policies. Purely additive and ABI-compatible; a hardened build is
deliberately not layout-compatible with a non-hardened one (never mix configurations).
[ADR-0043](docs/adr/0043-opt-in-debug-hardening.md). Closes #109.
- **`std::pmr::memory_resource` adapter — `PoolMemoryResource`.** A new header-only Adapter
([`pool_memory_resource.hpp`](src/main/cpp/it/d4np/memorypool/pool_memory_resource.hpp))
binds one `Pool` behind the runtime `std::pmr::memory_resource` interface, so a single
resource can back any `std::pmr` container through `std::pmr::polymorphic_allocator` without
the per-type `PoolAllocator<T>` rebind — the "door left open" in ADR-0018. Deterministic
`(bytes, alignment)` routing to the pool (over-sized / over-aligned requests fall back to a
configurable upstream resource; exhaustion throws `std::bad_alloc`), `is_equal` by
`(pool, upstream)` identity, gated behind `PBR_MEMORY_POOL_HAS_PMR` where `<memory_resource>`
is available. Purely additive and ABI-compatible — the frozen C ABI and existing C++ types
are unchanged; opens roadmap Milestone 9 (a `v1.2.0` candidate).
[ADR-0042](docs/adr/0042-pmr-memory-resource-adapter.md). Closes #107.
- **C4 component diagram of the pool internals** in the specification
([`docs/specs/01_spec_cpp_memory_pool.md`](docs/specs/01_spec_cpp_memory_pool.md), §4.2),
authored in Mermaid. [ADR-0041](docs/adr/0041-mermaid-diagram-tooling.md) records Mermaid
as the in-repo diagram tooling — C4 levels are drawn as flowcharts with `subgraph`
boundaries, and PlantUML, checked-in images, and Mermaid's experimental `C4Component` DSL
were considered and rejected. Closes the last open item of the specification review.
Documentation-only; no API change. Refs #105.

### Changed

- **`zh-Hans` / `ja` README translations re-synced to `v1.1.2`.** Carries the English
README's `v1.1.2` deltas into both locales — the `v1.1.2` status badge (and its
release-tag link) and the new `v1.1.2` status paragraph (the four BUG-0001…0004
fixes, the `docs-site` badge removal, and the translation re-sync). The
`translation-status.md` manifest's two README rows are re-pinned to the current
source commit (`d38b598`) and flipped from `stale` back to `translated`, clearing
the `i18n-freshness` flag the `v1.1.2` release raised. Documentation-only; no API change.
- **Specification reconciled with the as-built system.**
[`docs/specs/01_spec_cpp_memory_pool.md`](docs/specs/01_spec_cpp_memory_pool.md) was the
original greenfield brief and had drifted from the delivered (`v1.0.0`-frozen) library. It
now cross-links the realizing ADRs, formalizes the `§2`/`§3` subsection anchors already
referenced across the ADR set, disambiguates the `§2.2` dynamic-growth model (non-contiguous
chunk-linking; ADR-0022/0023/0024), documents the `§4.1`
block-size/alignment/strict-aliasing constraints (ADR-0009), the `§5.3` error semantics
(ADR-0012/0016) and `§5.4` introspection (ADR-0015/0025), and adds a `§7` spec→ADR map plus
the explicitly deferred items (#107 `pmr`, #108 fuzzing, #109 hardening). The
`zh-Hans`/`ja` spec translation rows are marked `stale` pending a follow-up re-sync.
Documentation-only; no API change. Refs #105.

## Released versions

Each released version is an **immutable** entry under [`docs/changelog/`](docs/changelog/) — one file per release, newest first ([ADR-0038](docs/adr/0038-changelog-version-split.md)). They are never edited after release; only the `Unreleased` block above changes during development.

| Version | Date | Highlights |
|---------|------|------------|
| [1.2.0](docs/changelog/v1/v1.2.0.md) | 2026-07-09 | Milestone 9 — std::pmr adapter, opt-in hardening, fuzzing harness, benchmark percentiles + jemalloc/tcmalloc baselines |
| [1.1.2](docs/changelog/v1/v1.1.2.md) | 2026-06-15 | Maintenance — InstrumentedPool/core bug fixes (BUG-0001…0004) + docs |
| [1.1.1](docs/changelog/v1/v1.1.1.md) | 2026-06-15 | Maintenance — bug ledger, PR-metadata policy, journal split, SECURITY.md, CI Node bump |
| [1.1.0](docs/changelog/v1/v1.1.0.md) | 2026-06-14 | Internationalization (zh-Hans / ja) & post-release governance |
Expand All @@ -122,4 +37,4 @@ Each released version is an **immutable** entry under [`docs/changelog/`](docs/c
| [0.2.0](docs/changelog/v0/v0.2.0.md) | 2026-06-11 | Core memory pool — single-threaded O(1) MVP |
| [0.1.0](docs/changelog/v0/v0.1.0.md) | 2026-06-10 | Build system & project skeleton |

[Unreleased]: https://github.com/danielPoloWork/pbr-cpp-memory-pool/compare/v1.1.2...HEAD
[Unreleased]: https://github.com/danielPoloWork/pbr-cpp-memory-pool/compare/v1.2.0...HEAD
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![API reference](https://img.shields.io/badge/API%20reference-Doxygen-1f6feb.svg)](https://danielpolowork.github.io/pbr-cpp-memory-pool/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Standard: C++17 / ANSI C](https://img.shields.io/badge/Standard-C%2B%2B17%20%2F%20ANSI%20C-blue.svg)](docs/specs/01_spec_cpp_memory_pool.md)
[![Status: v1.1.2 stable](https://img.shields.io/badge/Status-v1.1.2%20stable-brightgreen.svg)](https://github.com/danielPoloWork/pbr-cpp-memory-pool/releases/tag/v1.1.2)
[![Status: v1.2.0 stable](https://img.shields.io/badge/Status-v1.2.0%20stable-brightgreen.svg)](https://github.com/danielPoloWork/pbr-cpp-memory-pool/releases/tag/v1.2.0)

> Part of the **Purpose-Built References (PBR)** series — small, didactic, production-quality C/C++ reference implementations of high-performance building blocks.

Expand Down Expand Up @@ -193,6 +193,8 @@ Reports for other host × compiler combinations (Linux / GCC, Linux / Clang, mac

## Status

`v1.2.0` — **Milestone 9 (Ergonomics, Hardening & Tooling)**, the first post-`v1.0.0` MINOR. A wave of **additive, ABI-compatible** capabilities on top of the frozen public surface — the shipped library is byte-for-byte what `v1.1.x` produced in a default build. Adds a [`std::pmr::memory_resource` adapter](docs/adr/0042-pmr-memory-resource-adapter.md) (`PoolMemoryResource`, #107), **opt-in debug hardening** — freed-block poisoning, a guard word, and free-list safe-linking behind the `PBR_MEMORY_POOL_HARDENING` knob ([ADR-0043](docs/adr/0043-opt-in-debug-hardening.md), #109), a **coverage-guided fuzzing harness** ([ADR-0044](docs/adr/0044-coverage-guided-fuzzing-harness.md), #108), and a **benchmark extension** — p99 tail latency + `LD_PRELOAD` jemalloc/tcmalloc baselines ([ADR-0045](docs/adr/0045-benchmark-percentiles-and-external-baselines.md), #111). Every new feature is header-only, behind an opt-in knob, or test/bench-only; the `v1.0.0` C ABI and C++ types are unchanged. Five new ADRs (0041–0045) bring the total to 45. Release notes: [`docs/releases/v1.2.0.md`](docs/releases/v1.2.0.md). The earlier line:

`v1.1.2` — **maintenance** (bug fixes + documentation), a PATCH over `v1.1.1`. The public surface is unchanged — no API/ABI change. Fixes four verified, externally-reported defects (the first use of the in-repo [bug ledger](docs/bugs/), [ADR-0039](docs/adr/0039-bug-ledger-and-triage-protocol.md)): an `InstrumentedPool` growth-counter **data race** (BUG-0001), a `live_` counter **underflow** on foreign/double frees (BUG-0002), a missing `destroyed` event on move-assignment (BUG-0003), and a latent `grow_pool` **overflow** guard (BUG-0004). Also removes the redundant `docs-site` README badge and re-syncs the `zh-Hans`/`ja` translations. Release notes: [`docs/releases/v1.1.2.md`](docs/releases/v1.1.2.md). The earlier line:

`v1.1.1` — **maintenance** (documentation / process / tooling), the first post-`v1.1.0` PATCH. The shipped library is byte-identical to `v1.1.0` — no API/ABI/behaviour change. Adds the in-repo [bug ledger](docs/bugs/) + triage protocol ([ADR-0039](docs/adr/0039-bug-ledger-and-triage-protocol.md)), a [PR-metadata policy](docs/adr/0040-pull-request-metadata-policy.md), a [`SECURITY.md`](SECURITY.md), `packaging-smoke` CI for the vcpkg/Conan recipes, the [session journal](docs/journal/) ([ADR-0036](docs/adr/0036-session-journal-extraction.md)), the new-feature roadmap-placement rule ([ADR-0037](docs/adr/0037-new-feature-roadmap-placement.md)), and the per-release changelog split ([ADR-0038](docs/adr/0038-changelog-version-split.md)). Five new ADRs (0036–0040) bring the total to 40. Release notes: [`docs/releases/v1.1.1.md`](docs/releases/v1.1.1.md). The earlier line:
Expand All @@ -214,6 +216,7 @@ Reports for other host × compiler combinations (Linux / GCC, Linux / Clang, mac
| 6 | Observability & Decorators | ✅ complete |
| 7 | Release & Polish | ✅ complete |
| 8 | i18n & Post-Release Governance | ✅ complete |
| 9 | Ergonomics, Hardening & Tooling | ✅ complete |

See [`ROADMAP.md`](ROADMAP.md) for the per-task breakdown and the Spec Coverage Map at the bottom (traceability from spec sections to roadmap items).

Expand Down
1 change: 1 addition & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ Goal: a coherent, post-`v1.0.0` wave of **additive, ABI-compatible** capabilitie
- [x] 9.2 **Opt-in debug hardening** — freed-block poisoning, canaries, and free-list safe-linking (which also yields double-free detection); zero cost when the gate is off (issue #109). Decided in [ADR-0043](docs/adr/0043-opt-in-debug-hardening.md); implemented in [`memory_pool.cpp`](src/main/cpp/it/d4np/memorypool/memory_pool.cpp) behind the compile-time `PBR_MEMORY_POOL_HARDENING` knob (a `harden` CMake preset), with the swappable violation-handler surface in [`pool_hardening.hpp`](src/main/cpp/it/d4np/memorypool/pool_hardening.hpp) and [`pool_hardening_test.cpp`](src/test/cpp/it/d4np/memorypool/pool_hardening_test.cpp) (CTest `pool_hardening`). The "canary" is realized as one trailing **guard word** living in *added* slot stride — so the user-visible `block_size` and the ADR-0009 alignment guarantee are unchanged and the default build is byte-for-byte unchanged (the mechanism is fully compiled out). Poisoning (`0xDE`) catches use-after-free on the next allocation, the guard word catches a write past `block_size` and a double-free, and glibc-style safe-linking (`ptr XOR (slot_addr >> 12)`) protects the in-band next-link. A `harden` CI matrix cell builds and tests the hardened configuration on each Tier-1 platform. Works with fixed and dynamic pools across all three thread-safety policies.
- [x] 9.3 **Coverage-guided fuzzing harness** for the pool surface — a libFuzzer target, time-boxed in CI (issue #108). Decided in [ADR-0044](docs/adr/0044-coverage-guided-fuzzing-harness.md); implemented in [`pool_fuzz.cpp`](src/test/cpp/it/d4np/memorypool/pool_fuzz.cpp) as a stateful opcode interpreter with a shadow oracle that asserts the no-alias, canary-intact, foreign/NULL-no-op ([ADR-0012](docs/adr/0012-foreign-pointer-and-out-of-range-pointer-policy.md)) and `InstrumentedPool` accounting invariants across fixed and dynamic pools. One engine-agnostic source yields both the Clang-only libFuzzer target `pool_fuzz` (opt-in `PBR_MEMORY_POOL_BUILD_FUZZERS`, a `fuzz` preset under `-fsanitize=fuzzer,address,undefined`) and the always-built standalone [`pool_fuzz_replay`](src/test/cpp/it/d4np/memorypool/pool_fuzz_corpus/) target that replays the seed corpus as a portable regression gate (CTest `pool_fuzz_replay`) on every platform, including MSVC. A dedicated `fuzz` CI job replays the corpus and fuzzes for a bounded time on every PR; a crash is filed in the bug ledger ([ADR-0039](docs/adr/0039-bug-ledger-and-triage-protocol.md)). Test-only and additive — the release build and the benchmark numbers are untouched.
- [x] 9.4 **Benchmark extension** — external allocator baselines (jemalloc / tcmalloc) and p99 tail-latency reporting (issue #111). Decided in [ADR-0045](docs/adr/0045-benchmark-percentiles-and-external-baselines.md) (extends [ADR-0014](docs/adr/0014-microbenchmark-methodology-pool-vs-malloc.md)); implemented in [`pool_vs_malloc_bench.cpp`](src/bench/cpp/it/d4np/memorypool/pool_vs_malloc_bench.cpp). An opt-in `--percentiles` mode adds a separate per-operation p50/p90/p99/p999 table (the dynamic-pool growth row surfaces the amortized-growth spike the median hides); jemalloc / tcmalloc baselines are measured by re-running the bench under `LD_PRELOAD` (they take over global `malloc` on load, so they cannot be linked or `dlopen`'d beside the system allocator without crashing — an in-process attempt was tried and rejected); a `# allocator:` header discloses which allocator each run measured. The bench carries no allocator-specific code, so the default build keeps zero external dependencies (spec §3.3) and the [ADR-0014](docs/adr/0014-microbenchmark-methodology-pool-vs-malloc.md) aggregate table and its committed numbers are unchanged. A Linux `bench-baselines` CI cell re-runs the bench under each allocator's preload and asserts the disclosure + percentile table (non-asserting on numbers).
- [x] 9.5 **Close Milestone 9 → `v1.2.0`**: bump [`version.hpp`](src/main/cpp/it/d4np/memorypool/version.hpp) (`MINOR` 1→2, `PATCH` 2→0, `PBR_MEMORY_POOL_VERSION_STRING` `"1.2.0"`) with the `pool_smoke` version-check updated in lockstep; roll [`CHANGELOG.md`](CHANGELOG.md) `[Unreleased]` into the sealed [`docs/changelog/v1/v1.2.0.md`](docs/changelog/v1/v1.2.0.md) `## [1.2.0] — 2026-07-09` block (fresh empty `[Unreleased]`, table row + `compare/v1.2.0...HEAD` link); draft [`docs/releases/v1.2.0.md`](docs/releases/v1.2.0.md); refresh the README status badge (`v1.1.2` → `v1.2.0`), status paragraph, and milestone table (Milestone 9 → ✅ complete); mark the two `README.md` translation rows `stale` (re-synced in a post-release follow-up — the M8.8 / [ADR-0042](docs/adr/0042-pmr-memory-resource-adapter.md) i18n dance). Classified **MINOR** (additive surface, no API/ABI/behaviour change). The maintainer reviews and merges this PR, then the agent tags `v1.2.0` from `master` ([ADR-0008](docs/adr/0008-delegate-tag-creation-and-push-to-the-agent.md)) → `release.yml` drafts the GitHub Release → the maintainer clicks *Publish*. **This closes Milestone 9.**

---

Expand Down
Loading
Loading