LMMS
Loading...
Searching...
No Matches
SharedMemory.h
Go to the documentation of this file.
1/*
2 * SharedMemory.h
3 *
4 * Copyright (c) 2022 Dominic Clark <mrdomclark/at/gmail.com>
5 * Copyright (c) 2025-2026 Dalton Messmer <messmer.dalton/at/gmail.com>
6 *
7 * This file is part of LMMS - https://lmms.io
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program (see COPYING); if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA.
23 *
24 */
25
26#ifndef LMMS_SHARED_MEMORY_H
27#define LMMS_SHARED_MEMORY_H
28
29#include <memory>
30#include <memory_resource>
31#include <new>
32#include <string>
33#include <type_traits>
34
35
36namespace lmms
37{
38
39namespace detail
40{
41
42class SharedMemoryImpl;
43
45{
46public:
48 SharedMemoryData(std::string&& key, bool readOnly, bool isArray);
49 SharedMemoryData(std::string&& key, std::size_t size, bool readOnly, bool isArray);
50 SharedMemoryData(std::size_t size, bool readOnly, bool isArray);
52
55 {
56 auto temp = std::move(other);
57 swap(*this, temp);
58 return *this;
59 }
60
61 friend void swap(SharedMemoryData& a, SharedMemoryData& b) noexcept
62 {
63 using std::swap;
64 swap(a.m_key, b.m_key);
65 swap(a.m_impl, b.m_impl);
66 swap(a.m_ptr, b.m_ptr);
67 }
68
69 const std::string& key() const noexcept { return m_key; }
70 void* get() const noexcept { return m_ptr; }
71 std::size_t arraySize() const noexcept;
72
73private:
74 std::string m_key;
75 std::unique_ptr<SharedMemoryImpl> m_impl;
76 void* m_ptr = nullptr;
77};
78
79} // namespace detail
80
81
83class SharedMemoryResource final : public std::pmr::memory_resource
84{
85public:
87 SharedMemoryResource(void* buffer, std::size_t bufferSize) noexcept
88 : m_buffer{buffer}
89 , m_availableBytes{bufferSize}
90 , m_initialBuffer{buffer}
91 , m_initialBufferSize{bufferSize}
92 {}
93
98
105
107 auto availableBytes() const noexcept -> std::size_t { return m_availableBytes; }
108
109 template<typename T>
110 friend class SharedMemory;
111
112private:
114 void reset(void* newBuffer, std::size_t newBufferSize) noexcept
115 {
116 m_buffer = newBuffer;
117 m_availableBytes = newBufferSize;
118 m_initialBuffer = newBuffer;
119 m_initialBufferSize = newBufferSize;
120 }
121
122 void* do_allocate(std::size_t bytes, std::size_t alignment) override
123 {
124 void* p = std::align(alignment, bytes, m_buffer, m_availableBytes);
125 if (!p) { throw std::bad_alloc{}; }
126
127 m_buffer = static_cast<char*>(m_buffer) + bytes;
128 m_availableBytes -= bytes;
129 return p;
130 }
131 void do_deallocate(void*, std::size_t, std::size_t) override {} // no-op
132 bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override
133 {
134 return this == &other;
135 }
136
137private:
138 void* m_buffer = nullptr;
139 std::size_t m_availableBytes = 0;
140 void* m_initialBuffer = nullptr;
141 std::size_t m_initialBufferSize = 0;
142};
143
144
145template<typename T>
147{
148 // This is stricter than necessary, but keeps things easy for now
149 static_assert(std::is_trivial_v<T>, "objects held in shared memory must be trivial");
150 static_assert(sizeof(T) > 0);
151
152public:
153 SharedMemory() = default;
154 SharedMemory(const SharedMemory&) = delete;
158
159 void attach(std::string key)
160 {
161 m_data = detail::SharedMemoryData{std::move(key), std::is_const_v<T>, false};
162 }
163
164 void create(std::string key)
165 {
166 m_data = detail::SharedMemoryData{std::move(key), sizeof(T), std::is_const_v<T>, false};
167 }
168
169 void create()
170 {
171 m_data = detail::SharedMemoryData{sizeof(T), std::is_const_v<T>, false};
172 }
173
175 {
177 }
178
179 const std::string& key() const noexcept { return m_data.key(); }
180 T* get() const noexcept { return static_cast<T*>(m_data.get()); }
181
182 std::size_t size() const noexcept { return get() ? 1 : 0; }
183 std::size_t size_bytes() const noexcept { return get() ? sizeof(T) : 0; }
184
185 T* operator->() const noexcept { return get(); }
186 T& operator*() const noexcept { return *get(); }
187 explicit operator bool() const noexcept { return get() != nullptr; }
188
189private:
191};
192
193template<typename T>
194class SharedMemory<T[]>
195{
196 // This is stricter than necessary, but keeps things easy for now
197 static_assert(std::is_trivial_v<T>, "objects held in shared memory must be trivial");
198 static_assert(sizeof(T) > 0);
199
200public:
201 SharedMemory() = default;
202 SharedMemory(const SharedMemory&) = delete;
206
207 void attach(std::string key)
208 {
209 m_data = detail::SharedMemoryData{std::move(key), std::is_const_v<T>, true};
210 m_resource.reset(m_data.get(), size_bytes());
211 }
212
213 void create(std::string key, std::size_t size)
214 {
215 m_data = detail::SharedMemoryData{std::move(key), size * sizeof(T), std::is_const_v<T>, true};
216 m_resource.reset(m_data.get(), size_bytes());
217 }
218
219 void create(std::size_t size)
220 {
221 m_data = detail::SharedMemoryData{size * sizeof(T), std::is_const_v<T>, true};
222 m_resource.reset(m_data.get(), size_bytes());
223 }
224
226 {
228 m_resource.reset(nullptr, 0);
229 }
230
231 const std::string& key() const noexcept { return m_data.key(); }
232 T* get() const noexcept { return static_cast<T*>(m_data.get()); }
233
234 std::size_t size() const noexcept { return m_data.arraySize() / sizeof(T); }
235 std::size_t size_bytes() const noexcept { return m_data.arraySize(); }
236
237 T& operator[](std::size_t index) const noexcept { return get()[index]; }
238 explicit operator bool() const noexcept { return get() != nullptr; }
239
241
242private:
245};
246
247} // namespace lmms
248
249#endif // LMMS_SHARED_MEMORY_H
#define noexcept
Definition DistrhoDefines.h:72
#define final
Definition DistrhoDefines.h:74
uint8_t a
Definition Spc_Cpu.h:141
std::size_t size() const noexcept
Definition SharedMemory.h:234
SharedMemory(const SharedMemory &)=delete
detail::SharedMemoryData m_data
Definition SharedMemory.h:243
T & operator[](std::size_t index) const noexcept
Definition SharedMemory.h:237
SharedMemory & operator=(const SharedMemory &)=delete
void attach(std::string key)
Definition SharedMemory.h:207
SharedMemoryResource * resource() noexcept
Definition SharedMemory.h:240
void create(std::size_t size)
Definition SharedMemory.h:219
const std::string & key() const noexcept
Definition SharedMemory.h:231
void detach() noexcept
Definition SharedMemory.h:225
SharedMemory & operator=(SharedMemory &&)=default
SharedMemoryResource m_resource
Definition SharedMemory.h:244
void create(std::string key, std::size_t size)
Definition SharedMemory.h:213
SharedMemory(SharedMemory &&)=default
std::size_t size_bytes() const noexcept
Definition SharedMemory.h:235
T * get() const noexcept
Definition SharedMemory.h:232
std::size_t size() const noexcept
Definition SharedMemory.h:182
SharedMemory()=default
detail::SharedMemoryData m_data
Definition SharedMemory.h:190
T * get() const noexcept
Definition SharedMemory.h:180
SharedMemory(SharedMemory &&)=default
void attach(std::string key)
Definition SharedMemory.h:159
T * operator->() const noexcept
Definition SharedMemory.h:185
void create()
Definition SharedMemory.h:169
void create(std::string key)
Definition SharedMemory.h:164
std::size_t size_bytes() const noexcept
Definition SharedMemory.h:183
void detach() noexcept
Definition SharedMemory.h:174
T & operator*() const noexcept
Definition SharedMemory.h:186
SharedMemory & operator=(SharedMemory &&)=default
const std::string & key() const noexcept
Definition SharedMemory.h:179
SharedMemory(const SharedMemory &)=delete
SharedMemory & operator=(const SharedMemory &)=delete
Similar to std::pmr::monotonic_buffer_resource, but the initial buffer can be replaced.
Definition SharedMemory.h:84
void do_deallocate(void *, std::size_t, std::size_t) override
Definition SharedMemory.h:131
SharedMemoryResource(void *buffer, std::size_t bufferSize) noexcept
Definition SharedMemory.h:87
void reset(void *newBuffer, std::size_t newBufferSize) noexcept
Replaces the initial buffer.
Definition SharedMemory.h:114
std::size_t m_initialBufferSize
Definition SharedMemory.h:141
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
Definition SharedMemory.h:132
SharedMemoryResource(const SharedMemoryResource &)=delete
friend class SharedMemory
Definition SharedMemory.h:110
void reset() noexcept
Returns the buffer back to its initial state.
Definition SharedMemory.h:100
auto operator=(SharedMemoryResource &&) -> SharedMemoryResource &=default
SharedMemoryResource(SharedMemoryResource &&)=default
void * m_buffer
Definition SharedMemory.h:138
auto availableBytes() const noexcept -> std::size_t
Definition SharedMemory.h:107
void * do_allocate(std::size_t bytes, std::size_t alignment) override
Definition SharedMemory.h:122
auto operator=(const SharedMemoryResource &) -> SharedMemoryResource &=delete
std::size_t m_availableBytes
Definition SharedMemory.h:139
void * m_initialBuffer
Definition SharedMemory.h:140
Definition SharedMemory.h:45
friend void swap(SharedMemoryData &a, SharedMemoryData &b) noexcept
Definition SharedMemory.h:61
std::unique_ptr< SharedMemoryImpl > m_impl
Definition SharedMemory.h:75
void * m_ptr
Definition SharedMemory.h:76
std::string m_key
Definition SharedMemory.h:74
std::size_t arraySize() const noexcept
const std::string & key() const noexcept
Definition SharedMemory.h:69
void * get() const noexcept
Definition SharedMemory.h:70
Definition AudioBufferView.h:45
Definition AudioAlsa.cpp:35
Definition juce_Uuid.h:141
uch * p
Definition crypt.c:594
b
Definition crypt.c:628
ulg size
Definition extract.c:2350
#define const
Definition zconf.h:137