cpp-msgpack-rpc
0.2.0
An RPC library implementing MessagePack RPC.
Toggle main menu visibility
Loading...
Searching...
No Matches
shared_objects.h
Go to the documentation of this file.
1
/*
2
* Copyright 2024 MusicScience37 (Kenta Kabashima)
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
* http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
20
#pragma once
21
22
#include <atomic>
23
#include <memory>
24
#include <new>
25
#include <optional>
26
#include <utility>
27
#include <vector>
28
29
namespace
msgpack_rpc::util::impl
{
30
36
template
<
typename
T>
37
class
SharedObjectBuffer
{
38
public
:
42
SharedObjectBuffer
() noexcept = default;
43
50
[[nodiscard]]
bool
try_start_use
() noexcept {
51
int
empty = -1;
52
constexpr
int
initial = 1;
53
return
reference_count_
.compare_exchange_strong(empty, initial,
54
std::memory_order_acquire, std::memory_order_relaxed);
55
}
56
65
template
<
typename
... Args>
66
void
emplace
(Args&&... args) {
67
buffer_
.emplace(std::forward<Args>(args)...);
68
}
69
73
void
add_reference
() noexcept {
74
reference_count_
.fetch_add(1, std::memory_order_relaxed);
75
}
76
80
void
release
() noexcept {
81
const
int
reference_count =
82
reference_count_
.fetch_sub(1, std::memory_order_acq_rel);
83
if
(reference_count == 1) {
84
buffer_
.reset();
85
const
int
empty = -1;
86
reference_count_
.store(empty, std::memory_order_release);
87
}
88
}
89
95
[[nodiscard]] T*
get
() noexcept {
96
return
&(*buffer_);
// NOLINT
97
}
98
99
private
:
101
std::atomic<int>
reference_count_
{-1};
102
104
std::optional<T>
buffer_
{};
105
};
106
107
template
<
typename
T>
108
class
SharedObjectMemoryPool;
109
115
template
<
typename
T>
116
class
SharedObject
{
117
public
:
121
SharedObject
() noexcept = default;
122
129
explicit
SharedObject
(
SharedObjectBuffer
<T>* buffer,
130
std
::shared_ptr<
SharedObjectMemoryPool
<T>> memory_pool) noexcept
131
:
buffer_
(buffer),
memory_pool_
(
std
::move(memory_pool)) {}
132
138
SharedObject
(
const
SharedObject
& other) noexcept
139
:
buffer_
(other.buffer_),
memory_pool_
(other.memory_pool_) {
140
if
(
buffer_
!=
nullptr
) {
141
buffer_
->add_reference();
142
}
143
}
144
150
SharedObject
(
SharedObject
&& other) noexcept
151
:
buffer_
(std::exchange(other.buffer_,
nullptr
)),
152
memory_pool_
(std::exchange(other.memory_pool_,
153
std::shared_ptr<
SharedObjectMemoryPool<T>
>())) {}
154
161
SharedObject
&
operator=
(
const
SharedObject
& other)
noexcept
{
162
if
(
this
== &other) {
163
return
*
this
;
164
}
165
reset
();
166
buffer_
= other.buffer_;
167
memory_pool_
= other.memory_pool_;
168
if
(
buffer_
!=
nullptr
) {
169
buffer_
->add_reference();
170
}
171
return
*
this
;
172
}
173
180
SharedObject
&
operator=
(
SharedObject
&& other)
noexcept
{
181
reset
();
182
buffer_
= std::exchange(other.buffer_,
nullptr
);
183
memory_pool_
= std::exchange(
184
other.memory_pool_, std::shared_ptr<
SharedObjectMemoryPool<T>
>());
185
return
*
this
;
186
}
187
191
~SharedObject
() noexcept {
reset
(); }
192
196
void
reset
() noexcept {
197
if
(
buffer_
!=
nullptr
) {
198
buffer_
->release();
199
buffer_
=
nullptr
;
200
memory_pool_
.reset();
201
}
202
}
203
204
private
:
206
SharedObjectBuffer<T>
*
buffer_
{
nullptr
};
207
209
std::shared_ptr<SharedObjectMemoryPool<T>>
memory_pool_
{};
210
};
211
217
template
<
typename
T>
218
class
SharedObjectMemoryPool
219
:
public
std::enable_shared_from_this<SharedObjectMemoryPool<T>> {
220
public
:
227
static
std::shared_ptr<SharedObjectMemoryPool<T>>
create
(
228
std::size_t num_buffers) {
229
return
std::make_shared<SharedObjectMemoryPool<T>>(num_buffers);
230
}
231
237
explicit
SharedObjectMemoryPool
(std::size_t num_buffers)
238
:
buffers_
(num_buffers) {}
239
240
SharedObjectMemoryPool
(
const
SharedObjectMemoryPool
&) =
delete
;
241
SharedObjectMemoryPool
(
SharedObjectMemoryPool
&&) =
delete
;
242
SharedObjectMemoryPool
& operator=(
const
SharedObjectMemoryPool
&) =
delete
;
243
SharedObjectMemoryPool
& operator=(
SharedObjectMemoryPool
&&) =
delete
;
244
248
~SharedObjectMemoryPool
() =
default
;
249
257
template
<
typename
... Args>
258
[[nodiscard]]
SharedObject<T>
create
(Args&&... args) {
259
const
std::size_t initial_buffer_index =
next_buffer_index_
;
260
while
(
true
) {
261
const
std::size_t buffer_index =
next_buffer_index_
++;
262
next_buffer_index_
%=
buffers_
.size();
263
SharedObjectBuffer<T>
& buffer =
buffers_
[buffer_index];
264
if
(!buffer.
try_start_use
()) {
265
if
(
next_buffer_index_
== initial_buffer_index) {
266
throw
std::bad_alloc();
267
}
268
continue
;
269
}
270
271
try
{
272
buffer.
emplace
(std::forward<Args>(args)...);
273
return
SharedObject<T>
(&buffer, this->shared_from_this());
274
}
catch
(...) {
275
buffer.
release
();
276
throw
;
277
}
278
}
279
}
280
281
private
:
283
std::vector<SharedObjectBuffer<T>>
buffers_
;
284
286
std::size_t
next_buffer_index_
{0};
287
};
288
289
}
// namespace msgpack_rpc::util::impl
msgpack_rpc::util::impl::SharedObjectBuffer
Class of buffers of shared objects.
Definition
shared_objects.h:37
msgpack_rpc::util::impl::SharedObjectBuffer::get
T * get() noexcept
Access the object.
Definition
shared_objects.h:95
msgpack_rpc::util::impl::SharedObjectBuffer::add_reference
void add_reference() noexcept
Increase the reference count.
Definition
shared_objects.h:73
msgpack_rpc::util::impl::SharedObjectBuffer::SharedObjectBuffer
SharedObjectBuffer() noexcept=default
Constructor.
msgpack_rpc::util::impl::SharedObjectBuffer::reference_count_
std::atomic< int > reference_count_
Reference count. (-1 for unused buffer.).
Definition
shared_objects.h:101
msgpack_rpc::util::impl::SharedObjectBuffer::buffer_
std::optional< T > buffer_
Buffer.
Definition
shared_objects.h:104
msgpack_rpc::util::impl::SharedObjectBuffer::try_start_use
bool try_start_use() noexcept
Try to start to use.
Definition
shared_objects.h:50
msgpack_rpc::util::impl::SharedObjectBuffer::emplace
void emplace(Args &&... args)
Construct an object.
Definition
shared_objects.h:66
msgpack_rpc::util::impl::SharedObjectBuffer::release
void release() noexcept
Decrease the reference count and destruct the object if needed.
Definition
shared_objects.h:80
msgpack_rpc::util::impl::SharedObjectMemoryPool
Class of memory pools of shared objects.
Definition
shared_objects.h:219
msgpack_rpc::util::impl::SharedObjectMemoryPool::SharedObjectMemoryPool
SharedObjectMemoryPool(std::size_t num_buffers)
Constructor.
Definition
shared_objects.h:237
msgpack_rpc::util::impl::SharedObjectMemoryPool::buffers_
std::vector< SharedObjectBuffer< T > > buffers_
Buffers.
Definition
shared_objects.h:283
msgpack_rpc::util::impl::SharedObjectMemoryPool::next_buffer_index_
std::size_t next_buffer_index_
Index of the next buffer.
Definition
shared_objects.h:286
msgpack_rpc::util::impl::SharedObjectMemoryPool::create
static std::shared_ptr< SharedObjectMemoryPool< T > > create(std::size_t num_buffers)
Create a memory pool.
Definition
shared_objects.h:227
msgpack_rpc::util::impl::SharedObjectMemoryPool::create
SharedObject< T > create(Args &&... args)
Create a shared object.
Definition
shared_objects.h:258
msgpack_rpc::util::impl::SharedObjectMemoryPool::~SharedObjectMemoryPool
~SharedObjectMemoryPool()=default
Destructor.
msgpack_rpc::util::impl::SharedObject
Class to hold shared objects.
Definition
shared_objects.h:116
msgpack_rpc::util::impl::SharedObject::SharedObject
SharedObject(SharedObject &&other) noexcept
Move constructor.
Definition
shared_objects.h:150
msgpack_rpc::util::impl::SharedObject::operator=
SharedObject & operator=(const SharedObject &other) noexcept
Copy assignment operator.
Definition
shared_objects.h:161
msgpack_rpc::util::impl::SharedObject::reset
void reset() noexcept
Remove the buffer.
Definition
shared_objects.h:196
msgpack_rpc::util::impl::SharedObject::SharedObject
SharedObject(const SharedObject &other) noexcept
Copy constructor.
Definition
shared_objects.h:138
msgpack_rpc::util::impl::SharedObject::operator=
SharedObject & operator=(SharedObject &&other) noexcept
Move assignment operator.
Definition
shared_objects.h:180
msgpack_rpc::util::impl::SharedObject::~SharedObject
~SharedObject() noexcept
Destructor.
Definition
shared_objects.h:191
msgpack_rpc::util::impl::SharedObject::SharedObject
SharedObject() noexcept=default
Constructor.
msgpack_rpc::util::impl::SharedObject::buffer_
SharedObjectBuffer< T > * buffer_
Buffer of the shared object.
Definition
shared_objects.h:206
msgpack_rpc::util::impl::SharedObject::memory_pool_
std::shared_ptr< SharedObjectMemoryPool< T > > memory_pool_
Memory pool.
Definition
shared_objects.h:209
msgpack_rpc::util::impl
Namespace of internal implementations.
Definition
format_msgpack_object.h:27
std
STL namespace.
include
msgpack_rpc
util
impl
shared_objects.h
Generated on
for cpp-msgpack-rpc by
1.18.0