This repository was archived by the owner on Jun 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunique_buffer.hpp
More file actions
131 lines (108 loc) · 3.04 KB
/
Copy pathunique_buffer.hpp
File metadata and controls
131 lines (108 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//
// Unique buffer based on std::pmr::memory_resource.
//
// Copyright(c) 2020 Chronimal. All rights reserved.
//
// Licensed under the MIT license; A copy of the license that can be
// found in the LICENSE file.
//
#ifndef UB_TEMP_BUFFER_HPP_INCLUDED
#define UB_TEMP_BUFFER_HPP_INCLUDED
// Configure namespace preference for UniqueBuffer.
// By default namespace utl is used.
#define UB_NAMESPACE_NAME utl
// clang-format off
#ifndef UB_BEGIN_NAMESPACE
#define UB_BEGIN_NAMESPACE namespace UB_NAMESPACE_NAME {
#endif // UB_BEGIN_NAMESPAC
#ifndef UB_END_NAMESPACE
#define UB_END_NAMESPACE }
#endif // UB_END_NAMESPACE
// clang-format on
#include <memory_resource>
#include <bit>
UB_BEGIN_NAMESPACE
class UniqueBuffer
{
public:
UniqueBuffer(UniqueBuffer const&) = delete;
UniqueBuffer& operator=(UniqueBuffer const&) = delete;
UniqueBuffer() noexcept = default;
UniqueBuffer(std::size_t size)
: UniqueBuffer(size, std::pmr::get_default_resource())
{
}
UniqueBuffer(std::size_t size, std::pmr::memory_resource& memres, std::size_t alignment = alignof(std::max_align_t))
: UniqueBuffer(size, &memres, alignment)
{
}
UniqueBuffer(std::size_t size, std::pmr::memory_resource* memres, std::size_t alignment = alignof(std::max_align_t))
: buffer_{memres->allocate(size, alignment)}
, memres_{memres}
, size_{size}
, alignment_{alignment}
{
}
UniqueBuffer(UniqueBuffer&& other) noexcept
: buffer_{std::exchange(other.buffer_, nullptr)}
, memres_{std::exchange(other.memres_, nullptr)}
, size_{std::exchange(other.size_, 0)}
, alignment_{std::exchange(other.alignment_, 0)}
{
}
UniqueBuffer& operator=(UniqueBuffer&& other) noexcept
{
auto temp{std::move(other)};
swap(temp);
return *this;
}
~UniqueBuffer()
{
deallocate();
}
void reset() noexcept
{
deallocate();
size_ = alignment_ = 0;
memres_ = nullptr;
buffer_ = nullptr;
}
void swap(UniqueBuffer& other) noexcept
{
std::swap(buffer_, other.buffer_);
std::swap(memres_, other.memres_);
std::swap(size_, other.size_);
std::swap(alignment_, other.alignment_);
}
[[nodiscard]] void* get() const noexcept
{
return buffer_;
}
template<typename T, typename = std::enable_if_t<std::is_trivial_v<T> && std::is_standard_layout_v<T>>>
[[nodiscard]] T* as() const noexcept
{
return std::bit_cast<T*>(buffer_);
}
[[nodiscard]] std::size_t size() const noexcept
{
return size_;
}
[[nodiscard]] std::size_t alignment() const noexcept
{
return alignment_;
}
private:
void* buffer_{};
std::pmr::memory_resource* memres_{};
std::size_t size_{};
std::size_t alignment_{};
void deallocate() noexcept
{
if (memres_ != nullptr)
{
memres_->deallocate(buffer_, alignment_);
}
}
};
UB_END_NAMESPACE
#endif // UB_TEMP_BUFFER_HPP_INCLUDED