Corium 1.1.0
High-Performance Zero-Heap C++20 MPSC Application Runtime
Loading...
Searching...
No Matches
SharedMemory.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <cstddef>
10#include <cstdint>
11#include <string>
12#include <utility>
13
14#if defined(_WIN32) || defined(_WIN64)
15#ifndef NOMINMAX
16#define NOMINMAX
17#endif
18#ifndef WIN32_LEAN_AND_MEAN
19#define WIN32_LEAN_AND_MEAN
20#endif
21#include <windows.h>
22#define CORIUM_HAS_POSIX_SHM 0
23#elif __has_include(<sys/mman.h>) && __has_include(<unistd.h>) && __has_include(<fcntl.h>)
24#include <fcntl.h>
25#include <sys/mman.h>
26#include <sys/stat.h>
27#include <unistd.h>
28#define CORIUM_HAS_POSIX_SHM 1
29#else
30#define CORIUM_HAS_POSIX_SHM 0
31#endif
32
33namespace corium::ipc {
34
38public:
39 constexpr RawMemoryBuffer() noexcept = default;
40
41 constexpr RawMemoryBuffer(void* address, std::size_t size, bool isCreator = false) noexcept
42 : _address(address), _size(size), _isCreator(isCreator)
43 {}
44
45 [[nodiscard]] void* data() noexcept { return _address; }
46 [[nodiscard]] const void* data() const noexcept { return _address; }
47 [[nodiscard]] std::size_t size() const noexcept { return _size; }
48 [[nodiscard]] bool isValid() const noexcept { return _address != nullptr; }
49 [[nodiscard]] bool isCreator() const noexcept { return _isCreator; }
50
51private:
52 void* _address{nullptr};
53 std::size_t _size{0};
54 bool _isCreator{false};
55};
56
61public:
62 enum class AccessMode : uint8_t {
66 };
67
68 SharedMemory() noexcept = default;
69
71 {
72 close();
73 }
74
75 SharedMemory(const SharedMemory&) = delete;
77
78 SharedMemory(SharedMemory&& other) noexcept
79 : _name(std::move(other._name)),
80 _address(other._address),
81 _size(other._size),
82 _isCreator(other._isCreator)
83#if defined(_WIN32) || defined(_WIN64)
84 , _handle(other._handle)
85#elif CORIUM_HAS_POSIX_SHM
86 , _fd(other._fd)
87#endif
88 {
89 other._address = nullptr;
90 other._size = 0;
91 other._isCreator = false;
92#if defined(_WIN32) || defined(_WIN64)
93 other._handle = nullptr;
94#elif CORIUM_HAS_POSIX_SHM
95 other._fd = -1;
96#endif
97 }
98
100 {
101 if (this != &other) {
102 close();
103 _name = std::move(other._name);
104 _address = other._address;
105 _size = other._size;
106 _isCreator = other._isCreator;
107#if defined(_WIN32) || defined(_WIN64)
108 _handle = other._handle;
109 other._handle = nullptr;
110#elif CORIUM_HAS_POSIX_SHM
111 _fd = other._fd;
112 other._fd = -1;
113#endif
114 other._address = nullptr;
115 other._size = 0;
116 other._isCreator = false;
117 }
118 return *this;
119 }
120
126 bool open(const std::string& name, std::size_t size, AccessMode mode = AccessMode::CreateOrOpen) noexcept
127 {
128 close();
129 _name = normalizeName(name);
130 _size = size;
131
132#if defined(_WIN32) || defined(_WIN64)
133 DWORD protect = (mode == AccessMode::OpenReadOnly) ? PAGE_READONLY : PAGE_READWRITE;
134 DWORD desiredAccess = (mode == AccessMode::OpenReadOnly) ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS;
135
136 if (mode == AccessMode::CreateOrOpen) {
137 _handle = CreateFileMappingA(
138 INVALID_HANDLE_VALUE,
139 nullptr,
140 protect,
141 static_cast<DWORD>(size >> 32),
142 static_cast<DWORD>(size & 0xFFFFFFFF),
143 _name.c_str()
144 );
145 if (_handle) {
146 _isCreator = (GetLastError() != ERROR_ALREADY_EXISTS);
147 }
148 } else {
149 _handle = OpenFileMappingA(desiredAccess, FALSE, _name.c_str());
150 _isCreator = false;
151 }
152
153 if (!_handle) {
154 return false;
155 }
156
157 _address = MapViewOfFile(_handle, desiredAccess, 0, 0, size);
158 if (!_address) {
159 CloseHandle(_handle);
160 _handle = nullptr;
161 return false;
162 }
163 return true;
164#elif CORIUM_HAS_POSIX_SHM
165 int oflag = 0;
166 mode_t permissions = 0666;
167
168 if (mode == AccessMode::CreateOrOpen) {
169 oflag = O_CREAT | O_RDWR;
170 } else if (mode == AccessMode::OpenReadOnly) {
171 oflag = O_RDONLY;
172 } else {
173 oflag = O_RDWR;
174 }
175
176 _fd = ::shm_open(_name.c_str(), oflag, permissions);
177 if (_fd < 0) {
178 return false;
179 }
180
181 if (mode == AccessMode::CreateOrOpen) {
182 struct stat sb{};
183 if (::fstat(_fd, &sb) == 0 && sb.st_size < static_cast<off_t>(size)) {
184 if (::ftruncate(_fd, static_cast<off_t>(size)) != 0) {
185 ::close(_fd);
186 _fd = -1;
187 return false;
188 }
189 _isCreator = true;
190 }
191 }
192
193 int prot = (mode == AccessMode::OpenReadOnly) ? PROT_READ : (PROT_READ | PROT_WRITE);
194 _address = ::mmap(nullptr, size, prot, MAP_SHARED, _fd, 0);
195 if (_address == MAP_FAILED) {
196 _address = nullptr;
197 ::close(_fd);
198 _fd = -1;
199 return false;
200 }
201 return true;
202#else
203 (void)mode;
204 return false;
205#endif
206 }
207
209 void close() noexcept
210 {
211 if (_address) {
212#if defined(_WIN32) || defined(_WIN64)
213 UnmapViewOfFile(_address);
214 if (_handle) {
215 CloseHandle(_handle);
216 _handle = nullptr;
217 }
218#elif CORIUM_HAS_POSIX_SHM
219 ::munmap(_address, _size);
220 if (_fd >= 0) {
221 ::close(_fd);
222 _fd = -1;
223 }
224#endif
225 _address = nullptr;
226 _size = 0;
227 _isCreator = false;
228 }
229 }
230
232 static void unlink(const std::string& name) noexcept
233 {
234#if CORIUM_HAS_POSIX_SHM
235 std::string n = normalizeName(name);
236 ::shm_unlink(n.c_str());
237#else
238 (void)name;
239#endif
240 }
241
243 [[nodiscard]] void* data() noexcept { return _address; }
244 [[nodiscard]] const void* data() const noexcept { return _address; }
245
247 [[nodiscard]] std::size_t size() const noexcept { return _size; }
248
250 [[nodiscard]] bool isValid() const noexcept { return _address != nullptr; }
251
253 [[nodiscard]] bool isCreator() const noexcept { return _isCreator; }
254
256 [[nodiscard]] const std::string& name() const noexcept { return _name; }
257
258private:
259 static std::string normalizeName(const std::string& name)
260 {
261#if !defined(_WIN32) && !defined(_WIN64)
262 if (name.empty() || name[0] != '/') {
263 return "/" + name;
264 }
265#endif
266 return name;
267 }
268
269 std::string _name;
270 void* _address{nullptr};
271 std::size_t _size{0};
272 bool _isCreator{false};
273
274#if defined(_WIN32) || defined(_WIN64)
275 HANDLE _handle{nullptr};
276#elif CORIUM_HAS_POSIX_SHM
277 int _fd{-1};
278#endif
279};
280
281} // namespace corium::ipc
Non-allocating wrapper for fixed raw memory regions (e.g. multi-core SRAM, DMA buffers,...
Definition SharedMemory.hpp:37
std::size_t size() const noexcept
Definition SharedMemory.hpp:47
const void * data() const noexcept
Definition SharedMemory.hpp:46
void * data() noexcept
Definition SharedMemory.hpp:45
constexpr RawMemoryBuffer() noexcept=default
bool isCreator() const noexcept
Definition SharedMemory.hpp:49
bool isValid() const noexcept
Definition SharedMemory.hpp:48
Cross-platform zero-copy shared memory region wrapper. Manages OS-level shared memory allocation,...
Definition SharedMemory.hpp:60
SharedMemory & operator=(const SharedMemory &)=delete
SharedMemory & operator=(SharedMemory &&other) noexcept
Definition SharedMemory.hpp:99
const std::string & name() const noexcept
Name identifier of shared memory.
Definition SharedMemory.hpp:256
bool isCreator() const noexcept
Check if this process created the memory segment (useful for initialization).
Definition SharedMemory.hpp:253
SharedMemory(SharedMemory &&other) noexcept
Definition SharedMemory.hpp:78
void close() noexcept
Close and unmap the shared memory segment.
Definition SharedMemory.hpp:209
std::size_t size() const noexcept
Size of mapped shared memory buffer.
Definition SharedMemory.hpp:247
SharedMemory() noexcept=default
void * data() noexcept
Raw pointer to mapped shared memory buffer.
Definition SharedMemory.hpp:243
bool isValid() const noexcept
Check if mapped region is valid.
Definition SharedMemory.hpp:250
static void unlink(const std::string &name) noexcept
Remove shared memory identifier from OS namespace (POSIX shm_unlink).
Definition SharedMemory.hpp:232
bool open(const std::string &name, std::size_t size, AccessMode mode=AccessMode::CreateOrOpen) noexcept
Create or attach to a shared memory region.
Definition SharedMemory.hpp:126
AccessMode
Definition SharedMemory.hpp:62
SharedMemory(const SharedMemory &)=delete
const void * data() const noexcept
Definition SharedMemory.hpp:244
Definition DomainSocket.hpp:35