lintel 0.2.0
Loading...
Searching...
No Matches
ShmConstructors.h
Go to the documentation of this file.
1#ifndef LINTEL_SHMCONSTRUCTORS_H
2#define LINTEL_SHMCONSTRUCTORS_H
3
4#include <boost/container/map.hpp>
5#include <boost/container/string.hpp>
6#include <boost/container/vector.hpp>
7#include <boost/date_time/posix_time/posix_time.hpp>
8#include <boost/interprocess/managed_mapped_file.hpp>
9#include <boost/interprocess/sync/named_semaphore.hpp>
10
11#include <array>
12#include <chrono>
13#include <cstddef>
14#include <functional>
15#include <memory>
16#include <mutex>
17#include <stdexcept>
18#include <string>
19#include <utility>
20
24
25namespace lintel {
33{
34public:
35 std::shared_ptr<boost::interprocess::managed_mapped_file> m_managedMappedFile;
36 std::shared_ptr<SharedMemorySegment> m_sharedMemorySegment;
37 // Cross-process binary semaphore guarding the segment's remap and
38 // construct critical sections. Acquired (as a mutex) around grow/shrink
39 // and every find_or_construct so no process references the mapped file
40 // while another process resizes/reopens it.
41 std::unique_ptr<boost::interprocess::named_semaphore> m_remapSemaphore;
42 // Typed allocator adapter of this segment. Created on demand and reset
43 // whenever the mapping is replaced, so accessors always refer to the
44 // segment manager of the current mapping.
45 std::shared_ptr<ShmSegmentAccessor::Allocator> m_segmentAllocator;
46};
47
48namespace shm {
49
51 using SegmentManager = boost::interprocess::managed_mapped_file::segment_manager;
52
54 template<class Object> using SegmentAllocator = boost::interprocess::allocator<Object, SegmentManager>;
55
57 using String = boost::container::basic_string<char, std::char_traits<char>, SegmentAllocator<char>>;
58
60 template<class Key, class Value>
61 using Map = boost::container::map<Key, Value, std::less<Key>, SegmentAllocator<std::pair<const Key, Value>>>;
62
64 template<class Object> using Vector = boost::container::vector<Object, SegmentAllocator<Object>>;
65
76 {
77 public:
80 static constexpr std::chrono::seconds kDefaultWaitTimeout{ 30 };
81
86 explicit SegmentSemaphoreGuard(boost::interprocess::named_semaphore &semaphore,
87 std::chrono::steady_clock::duration timeout = kDefaultWaitTimeout)
88 : m_semaphore(&semaphore)
89 {
90 const auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
91 const auto deadline =
92 boost::posix_time::microsec_clock::universal_time() + boost::posix_time::microseconds(microseconds);
93 if (!m_semaphore->timed_wait(deadline)) {
94 // A timed-out guard must not post on destruction - that would hand
95 // the lock to the next waiter even though we never owned it.
96 m_semaphore = nullptr;
97 throw std::runtime_error(
98 "timed out acquiring the shared memory segment remap semaphore; "
99 "a previous process may have crashed while holding it");
100 }
101 }
102
104 {
105 if (m_semaphore != nullptr) { m_semaphore->post(); }
106 }
107
109
111
112 private:
113 boost::interprocess::named_semaphore *m_semaphore;
114 };
115
124 template<class Object, std::size_t Size>
125 std::array<Object, Size> &constructArray(SharedMemoryService &service,
126 const std::shared_ptr<SharedMemorySegment> &segment,
127 const std::string &name)
128 {
129 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
130 auto &handle = service.segmentOf(segment->getName());
131 SegmentSemaphoreGuard gate(*handle.m_remapSemaphore);
132 return *(handle.m_managedMappedFile->find_or_construct<std::array<Object, Size>>(name.c_str())());
133 }
134
143 template<class Key, class Value>
145 const std::shared_ptr<SharedMemorySegment> &segment,
146 const std::string &name)
147 {
148 using pairType = std::pair<const Key, Value>;
150 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
151 auto &handle = service.segmentOf(segment->getName());
152 SegmentSemaphoreGuard gate(*handle.m_remapSemaphore);
153 persistentMapAllocator allocator(handle.m_managedMappedFile->get_segment_manager());
155 handle.m_managedMappedFile->find_or_construct<Map<Key, Value>>(name.c_str())(std::less<Key>(), allocator);
156 LOG_TRACE("map {}", map->size());
157 return *map;
158 }
159
167 template<class Object>
169 const std::shared_ptr<SharedMemorySegment> &segment,
170 const std::string &name)
171 {
173 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
174 auto &handle = service.segmentOf(segment->getName());
175 SegmentSemaphoreGuard gate(*handle.m_remapSemaphore);
176 persistentVectorAllocator allocator(handle.m_managedMappedFile->get_segment_manager());
177 return *(handle.m_managedMappedFile->find_or_construct<Vector<Object>>(name.c_str())(allocator));
178 }
179
187 template<class Object>
189 const std::shared_ptr<SharedMemorySegment> &segment,
190 const std::string &name)
191 {
192 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
193 auto &handle = service.segmentOf(segment->getName());
194 SegmentSemaphoreGuard gate(*handle.m_remapSemaphore);
195 return *(handle.m_managedMappedFile->find_or_construct<Object>(name.c_str())());
196 }
197
208 template<class Object, class... Args>
210 const std::shared_ptr<SharedMemorySegment> &segment,
211 const std::string &name,
212 Args &&...args)
213 {
214 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
215 auto &handle = service.segmentOf(segment->getName());
216 SegmentSemaphoreGuard gate(*handle.m_remapSemaphore);
217 return *(handle.m_managedMappedFile->find_or_construct<Object>(name.c_str())(std::forward<Args>(args)...));
218 }
219
227 const std::shared_ptr<SharedMemorySegment> &segment,
228 const std::string &name)
229 {
230 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
231 auto &handle = service.segmentOf(segment->getName());
232 SegmentSemaphoreGuard gate(*handle.m_remapSemaphore);
233 SegmentAllocator<char> charallocator(handle.m_managedMappedFile->get_segment_manager());
235 myString = name.c_str();
236 return myString;
237 }
238
244 const std::shared_ptr<SharedMemorySegment> &segment)
245 {
246 std::lock_guard<std::mutex> lock(service.segmentsMutexOf());
247 auto found = service.segmentsOf().find(segment->getName());
248 if (found == service.segmentsOf().end()) { return nullptr; }
249 SegmentSemaphoreGuard gate(*found->second->m_remapSemaphore);
250 return found->second->m_managedMappedFile->get_segment_manager();
251 }
252
253}// namespace shm
254
255}// namespace lintel
256#endif// LINTEL_SHMCONSTRUCTORS_H
#define LOG_TRACE(message,...)
Definition LoggerService.h:128
Definition ShmConstructors.h:33
std::shared_ptr< SharedMemorySegment > m_sharedMemorySegment
Definition ShmConstructors.h:36
std::unique_ptr< boost::interprocess::named_semaphore > m_remapSemaphore
Definition ShmConstructors.h:41
std::shared_ptr< ShmSegmentAccessor::Allocator > m_segmentAllocator
Definition ShmConstructors.h:45
std::shared_ptr< boost::interprocess::managed_mapped_file > m_managedMappedFile
Definition ShmConstructors.h:35
Definition SharedMemoryService.h:37
Definition ShmConstructors.h:76
~SegmentSemaphoreGuard()
Definition ShmConstructors.h:103
SegmentSemaphoreGuard(const SegmentSemaphoreGuard &)=delete
static constexpr std::chrono::seconds kDefaultWaitTimeout
Definition ShmConstructors.h:80
SegmentSemaphoreGuard & operator=(const SegmentSemaphoreGuard &)=delete
SegmentSemaphoreGuard(boost::interprocess::named_semaphore &semaphore, std::chrono::steady_clock::duration timeout=kDefaultWaitTimeout)
Definition ShmConstructors.h:86
boost::container::map< Key, Value, std::less< Key >, SegmentAllocator< std::pair< const Key, Value > > > Map
Definition ShmConstructors.h:61
Object & constructObject(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment, const std::string &name)
Definition ShmConstructors.h:188
std::array< Object, Size > & constructArray(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment, const std::string &name)
Definition ShmConstructors.h:125
Object & constructObjectWith(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment, const std::string &name, Args &&...args)
Definition ShmConstructors.h:209
boost::container::basic_string< char, std::char_traits< char >, SegmentAllocator< char > > String
Definition ShmConstructors.h:57
String constructString(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment, const std::string &name)
Definition ShmConstructors.h:226
boost::interprocess::managed_mapped_file::segment_manager SegmentManager
Definition ShmConstructors.h:51
SegmentManager * segmentManagerOf(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment)
Definition ShmConstructors.h:243
boost::interprocess::allocator< Object, SegmentManager > SegmentAllocator
Definition ShmConstructors.h:54
Map< Key, Value > & constructMap(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment, const std::string &name)
Definition ShmConstructors.h:144
boost::container::vector< Object, SegmentAllocator< Object > > Vector
Definition ShmConstructors.h:64
Vector< Object > & constructVector(SharedMemoryService &service, const std::shared_ptr< SharedMemorySegment > &segment, const std::string &name)
Definition ShmConstructors.h:168
Definition BaseFeature.h:6
@ Object
Definition SharedMemoryRepository.h:19
constexpr std::string_view type_name()
Definition TypeName.h:9