2020#if defined(_MSC_VER)
2121#include < windows.h>
2222#include < tchar.h>
23+ #else
24+ #include < sys/mman.h>
25+ #include < sys/stat.h>
26+ #include < fcntl.h>
27+ #include < unistd.h>
28+ #include < cerrno>
2329#endif
2430
2531namespace slick {
@@ -42,6 +48,10 @@ class SlickQueue {
4248#if defined(_MSC_VER)
4349 HANDLE hMapFile_ = nullptr ;
4450 LPVOID lpvMem_ = nullptr ;
51+ #else
52+ int shm_fd_ = -1 ;
53+ void * lpvMem_ = nullptr ;
54+ std::string shm_name_;
4555#endif
4656
4757public:
@@ -83,8 +93,21 @@ class SlickQueue {
8393 CloseHandle (hMapFile_);
8494 hMapFile_ = nullptr ;
8595 }
96+ #else
97+ if (lpvMem_) {
98+ auto BF_SZ = static_cast <size_t >(64 + sizeof (slot) * size_ + sizeof (T) * size_);
99+ munmap (lpvMem_, BF_SZ);
100+ lpvMem_ = nullptr ;
101+ }
102+ if (shm_fd_ != -1 ) {
103+ close (shm_fd_);
104+ shm_fd_ = -1 ;
105+ }
106+ if (own_ && !shm_name_.empty ()) {
107+ shm_unlink (shm_name_.c_str ());
108+ }
86109#endif
87-
110+
88111 if (!use_shm_) {
89112 delete[] data_;
90113 data_ = nullptr ;
@@ -171,7 +194,7 @@ class SlickQueue {
171194
172195#if defined(_MSC_VER)
173196 void allocate_shm_data (const char * const shm_name, bool open_only) {
174- SIZE_T BF_SZ;
197+ SIZE_T BF_SZ = 64 + sizeof (slot) * size_ + sizeof (T) * size_ ;
175198 hMapFile_ = NULL ;
176199 if (open_only) {
177200 hMapFile_ = OpenFileMapping (FILE_MAP_ALL_ACCESS, FALSE , (LPCWSTR)shm_name);
@@ -188,13 +211,10 @@ class SlickQueue {
188211 }
189212 mask_ = *reinterpret_cast <uint32_t *>(reinterpret_cast <uint8_t *>(lpvMem_) + sizeof (std::atomic_uint_fast64_t )) - 1 ;
190213 size_ = mask_ + 1025 ;
191- BF_SZ = 64 + sizeof (slot) * size_ + sizeof (T) * size_;
192214 UnmapViewOfFile (lpvMem_);
193215 lpvMem_ = nullptr ;
194216 }
195217 else {
196- BF_SZ = 64 + sizeof (slot) * size_ + sizeof (T) * size_;
197-
198218 hMapFile_ = CreateFileMapping (
199219 INVALID_HANDLE_VALUE, // use paging file
200220 NULL , // default security
@@ -207,7 +227,7 @@ class SlickQueue {
207227 own_ = false ;
208228 auto err = GetLastError ();
209229 if (hMapFile_ == NULL ) {
210- throw std::runtime_error (" Failed to create shm. err=" + std::to_string (err));
230+ throw std::runtime_error (" Failed to create shm. err=" + std::to_string (err));
211231 }
212232
213233 if (err != ERROR_ALREADY_EXISTS) {
@@ -234,7 +254,69 @@ class SlickQueue {
234254 }
235255 }
236256#else
237- void allocateShmData (const char * const shm_name) noexcept {
257+ void allocate_shm_data (const char * const shm_name, bool open_only) {
258+ size_t BF_SZ = 64 + sizeof (slot) * size_ + sizeof (T) * size_;
259+ shm_name_ = shm_name;
260+ if (open_only) {
261+ shm_fd_ = shm_open (shm_name, O_RDWR, 0666 );
262+ if (shm_fd_ == -1 ) {
263+ throw std::runtime_error (" Failed to open shm. err=" + std::to_string (errno));
264+ }
265+
266+ void * tmp = mmap (nullptr , 64 , PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_, 0 );
267+ if (tmp == MAP_FAILED) {
268+ throw std::runtime_error (" Failed to map shm header. err=" + std::to_string (errno));
269+ }
270+ mask_ = *reinterpret_cast <uint32_t *>(reinterpret_cast <uint8_t *>(tmp) + sizeof (std::atomic_uint_fast64_t )) - 1 ;
271+ size_ = mask_ + 1025 ;
272+ munmap (tmp, 64 );
273+
274+ lpvMem_ = mmap (nullptr , BF_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_, 0 );
275+ if (lpvMem_ == MAP_FAILED) {
276+ throw std::runtime_error (" Failed to map shm. err=" + std::to_string (errno));
277+ }
278+
279+ reserved_ = reinterpret_cast <std::atomic_uint_fast64_t *>(lpvMem_);
280+ control_ = reinterpret_cast <slot*>((uint8_t *)lpvMem_ + 64 );
281+ data_ = reinterpret_cast <T*>((uint8_t *)lpvMem_ + 64 + sizeof (slot) * size_);
282+ own_ = false ;
283+ } else {
284+ shm_fd_ = shm_open (shm_name, O_RDWR | O_CREAT | O_EXCL, 0666 );
285+ if (shm_fd_ == -1 ) {
286+ if (errno != EEXIST) {
287+ throw std::runtime_error (" Failed to create shm. err=" + std::to_string (errno));
288+ }
289+ shm_fd_ = shm_open (shm_name, O_RDWR, 0666 );
290+ if (shm_fd_ == -1 ) {
291+ throw std::runtime_error (" Failed to open existing shm. err=" + std::to_string (errno));
292+ }
293+ own_ = false ;
294+ } else {
295+ own_ = true ;
296+ }
297+
298+ if (own_) {
299+ if (ftruncate (shm_fd_, BF_SZ) == -1 ) {
300+ throw std::runtime_error (" Failed to size shm. err=" + std::to_string (errno));
301+ }
302+ }
303+
304+ lpvMem_ = mmap (nullptr , BF_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_, 0 );
305+ if (lpvMem_ == MAP_FAILED) {
306+ throw std::runtime_error (" Failed to map shm. err=" + std::to_string (errno));
307+ }
308+
309+ if (own_) {
310+ reserved_ = new (lpvMem_) std::atomic_uint_fast64_t { 0 };
311+ *reinterpret_cast <uint32_t *>(reinterpret_cast <uint8_t *>(lpvMem_) + sizeof (std::atomic_uint_fast64_t )) = mask_ + 1 ;
312+ control_ = new ((uint8_t *)lpvMem_ + 64 ) slot[size_];
313+ data_ = new ((uint8_t *)lpvMem_ + 64 + sizeof (slot) * size_) T[size_];
314+ } else {
315+ reserved_ = reinterpret_cast <std::atomic_uint_fast64_t *>(lpvMem_);
316+ control_ = reinterpret_cast <slot*>((uint8_t *)lpvMem_ + 64 );
317+ data_ = reinterpret_cast <T*>((uint8_t *)lpvMem_ + 64 + sizeof (slot) * size_);
318+ }
319+ }
238320 }
239321#endif
240322
0 commit comments