{"slug": "custom-memory-resource-implementation-with-an-atomic-monotonic-buffer-allocator", "title": "Custom memory_resource implementation with an atomic monotonic buffer allocator supporting aligned, lock-free allocations on a preallocated memory region.", "summary": "This article describes a custom C++ memory resource implementation called `monotonic_atomic_buffer`, which provides lock-free, aligned memory allocations from a preallocated buffer using atomic operations. The allocator uses a monotonic bump-pointer strategy with atomic compare-and-exchange to safely manage concurrent allocations without mutexes, and it never deallocates individual allocations. The implementation is designed for high-performance scenarios requiring thread-safe allocation from a fixed-size memory region.", "body_md": "monotonic_atomic_buffer.hpp\n\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      \nLearn more about bidirectional Unicode characters\n\n \n    Show hidden characters\n\n// Copyright (c) May 2026 Félix-Olivier Dumas. All rights reserved.\n\n// Licensed under the terms described in the LICENSE file\n\n#pragma once\n\n#include <cstddef>\n\n#include <atomic>\n\n#include <stdexcept>\n\nnamespace exotic::memory {\n\nclass memory_resource {\n\npublic:\n\n    virtual ~memory_resource() = default;\n\npublic:\n\n    [[nodiscard]] void* allocate(std::size_t bytes, std::size_t alignment) noexcept {\n\n        if (alignment == 0 || (alignment & (alignment - 1)) != 0) [[unlikely]]\n\n            throw std::invalid_argument(\"alignment must be a power of two\");\n\n        return do_allocate(bytes, alignment);\n\n    }\n\n    void deallocate(void* p, std::size_t bytes, std::size_t alignment) noexcept {\n\n        if (alignment == 0 || (alignment & (alignment - 1)) != 0) [[unlikely]]\n\n            throw std::invalid_argument(\"alignment must be a power of two\");\n\n        do_deallocate(p, bytes, alignment);\n\n    }\n\n    bool is_equal(const memory_resource& other) const noexcept {\n\n        return do_is_equal(other);\n\n    }\n\nprotected:\n\n    virtual void* do_allocate(std::size_t bytes, std::size_t alignment) = 0;\n\n    virtual void do_deallocate(void* ptr, std::size_t bytes, std::size_t alignment) = 0;\n\n    virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;\n\n};\n\nstruct monotonic_atomic_buffer : public memory_resource {\n\npublic:\n\n    explicit monotonic_atomic_buffer(std::size_t p_capacity)\n\n        : capacity_(p_capacity)\n\n        , offset_(0)\n\n        , buffer_(new std::byte[p_capacity])\n\n    {}\n\n    monotonic_atomic_buffer(const monotonic_atomic_buffer&) = delete;\n\n    monotonic_atomic_buffer& operator=(const monotonic_atomic_buffer&) = delete;\n\n    ~monotonic_atomic_buffer() noexcept override {\n\n        delete[] buffer_;\n\n    }\n\nprotected:\n\n    void* do_allocate(std::size_t bytes, std::size_t alignment) override {\n\n        std::size_t current = offset_.load(std::memory_order_relaxed);\n\n        while (true) {\n\n            std::size_t aligned = (current + (alignment - 1)) & ~(alignment - 1);\n\n            std::size_t next = aligned + bytes;\n\n            if (next > capacity_)\n\n                return nullptr;\n\n            if (offset_.compare_exchange_weak(\n\n                current,\n\n                next,\n\n                std::memory_order_relaxed)) {\n\n                return buffer_ + aligned;\n\n            }\n\n        }\n\n    }\n\n    void do_deallocate(void*, std::size_t, std::size_t) override {}\n\n    bool do_is_equal(const memory_resource& other) const noexcept override {\n\n        return this == &other;\n\n    }\n\npublic:\n\n    [[nodiscard]] constexpr std::size_t capacity() const noexcept { return capacity_; }\n\n    [[nodiscard]] std::size_t size() const noexcept { return offset_.load(std::memory_order_relaxed); }\n\nprivate:\n\n    std::byte* buffer_;\n\n    std::atomic<std::size_t> offset_;\n\n    std::size_t capacity_;\n\n};\n\n}", "url": "https://wpnews.pro/news/custom-memory-resource-implementation-with-an-atomic-monotonic-buffer-allocator", "canonical_source": "https://gist.github.com/unrays/f311c653d7f57b458d87c405e352602f", "published_at": "2026-05-22 19:52:04+00:00", "updated_at": "2026-05-22 20:08:35.792460+00:00", "lang": "en", "topics": ["developer-tools", "open-source", "data", "hardware", "research"], "entities": ["Félix-Olivier Dumas", "exotic::memory"], "alternates": {"html": "https://wpnews.pro/news/custom-memory-resource-implementation-with-an-atomic-monotonic-buffer-allocator", "markdown": "https://wpnews.pro/news/custom-memory-resource-implementation-with-an-atomic-monotonic-buffer-allocator.md", "text": "https://wpnews.pro/news/custom-memory-resource-implementation-with-an-atomic-monotonic-buffer-allocator.txt", "jsonld": "https://wpnews.pro/news/custom-memory-resource-implementation-with-an-atomic-monotonic-buffer-allocator.jsonld"}}