C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
atomic_readable_buffer.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <algorithm>
26#include <array>
27#include <atomic>
28#include <concepts>
29#include <cstddef>
30#include <memory>
31#include <memory_resource>
32#include <ranges>
33#include <utility>
34
35#if __has_include(<version> )
36#include <version>
37#endif
38
39namespace essence {
44 template <std::default_initializable T>
46 public:
47 using allocator_traits_type = std::allocator_traits<std::pmr::polymorphic_allocator<T>>;
48
53 explicit atomic_readable_buffer(std::pmr::memory_resource* resource = std::pmr::new_delete_resource())
54 : size_{}, allocator_{resource ? resource : std::pmr::new_delete_resource()} {
55 reset();
56 }
57
61 void reset() {
62 update(std::array<T, 0>{});
63 }
64
70 template <std::ranges::forward_range Range>
71 requires(std::convertible_to<std::ranges::range_value_t<Range>, T> && std::ranges::sized_range<Range>)
72 void update(Range&& range) {
73 auto size = std::ranges::size(range);
74
75 auto storage = allocator_traits_type::allocate(allocator_, size);
76
77 for (auto ptr = storage, ptr_end = storage + size; ptr < ptr_end; ++ptr) {
78 std::construct_at(ptr);
79 }
80
81 std::shared_ptr<T> buffer{storage, [size, allocator = allocator_](T* inner) mutable {
82 std::destroy(inner, inner + size);
83 allocator_traits_type::deallocate(allocator, inner, size);
84 }};
85
86 std::ranges::copy(range, buffer.get());
87 size_ = size;
88
89 std::atomic_store_explicit(&buffer_, buffer, std::memory_order::release);
90 }
91
96 std::pair<std::shared_ptr<T>, std::size_t> get() const {
97 auto buffer = std::atomic_load_explicit(&buffer_, std::memory_order::acquire);
98
99 return {buffer, size_};
100 }
101
102 private:
103 std::size_t size_;
104 std::pmr::polymorphic_allocator<T> allocator_;
105
106#if __cpp_lib_atomic_shared_ptr >= 201711L
107 std::atomic<std::shared_ptr<T>> buffer_;
108#else
109 std::shared_ptr<T> buffer_;
110#endif
111 };
112} // namespace essence
A safe buffer that can be atomically replaced and read.
Definition atomic_readable_buffer.hpp:45
void reset()
Resets the buffer.
Definition atomic_readable_buffer.hpp:61
std::pair< std::shared_ptr< T >, std::size_t > get() const
Retrieves the current buffer.
Definition atomic_readable_buffer.hpp:96
atomic_readable_buffer(std::pmr::memory_resource *resource=std::pmr::new_delete_resource())
Constructs the object with a PMR resource.
Definition atomic_readable_buffer.hpp:53
void update(Range &&range)
Updated the entire buffer.
Definition atomic_readable_buffer.hpp:72