View on GitHub

Vistle

Distributed Data-parallel Scientific Visualization in VR

shm.h
Go to the documentation of this file.
1#ifndef SHM_H
2#define SHM_H
3
4#include <memory>
5#include <array>
6#include <mutex>
7#include <atomic>
8#include <map>
9
10#ifdef NO_SHMEM
11#include <memory>
12#include <string>
13#include <vector>
14#include <map>
15#else
17#include <boost/interprocess/containers/vector.hpp>
18#include <boost/interprocess/containers/string.hpp>
19#include <boost/interprocess/containers/map.hpp>
20#ifdef _WIN32
21#include <boost/interprocess/managed_windows_shared_memory.hpp>
22#else
23#include <boost/interprocess/managed_shared_memory.hpp>
24#include <pthread.h>
25#endif
26#endif
27
28#include "archives_config.h"
29
32
33#include "export.h"
34#include "index.h"
35//#include "shm_array.h"
36#include "shmname.h"
37#include "shmdata.h"
38
39#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
40#define SHMBARRIER
41#endif
42
43//#define SHMDEBUG
44//#define SHMPUBLISH
45
46namespace vistle {
47
48#ifdef NO_SHMEM
49
50typedef ShmData *shm_handle_t;
51
52#else
53
54#ifdef _WIN32
55typedef boost::interprocess::managed_windows_shared_memory managed_shm;
56#else
57typedef boost::interprocess::managed_shared_memory managed_shm;
58#endif
59
60typedef managed_shm::handle_t shm_handle_t;
61#endif
62
63namespace message {
64class MessageQueue;
65}
66
68public:
69 shm_exception(const std::string &what = "shared memory error"): exception(what) {}
70};
71
72class Object;
73struct ObjectData;
74template<class T, class allocator>
75class shm_array;
76
77#ifdef SHMDEBUG
78struct ShmDebugInfo {
79 shm_name_t name;
80 shm_handle_t handle;
81 char deleted;
82 char type;
83
84 ShmDebugInfo(char type = '\0', const std::string &name = "", shm_handle_t handle = 0)
85 : handle(handle), deleted(0), type(type)
86 {
87 memset(this->name, '\0', sizeof(this->name));
88 strncpy(this->name, name.c_str(), sizeof(this->name) - 1);
89 }
90};
91#endif
92
93template<typename T>
94struct shm {
95#ifdef NO_SHMEM
97 typedef std::basic_string<T> string;
98 typedef std::vector<T> vector;
100 typedef array *array_ptr;
101 struct Constructor {
102 std::string name;
103
104 Constructor(const std::string &name);
105 ~Constructor();
106 template<typename... Args>
107 T *operator()(Args &&...args);
108 };
109 static Constructor construct(const std::string &name) { return Constructor(name); }
110#else
111 typedef boost::interprocess::allocator<T, managed_shm::segment_manager> allocator;
112 typedef boost::interprocess::basic_string<T, std::char_traits<T>, allocator> string;
113 typedef boost::interprocess::vector<T, allocator> vector;
115 typedef boost::interprocess::offset_ptr<array> array_ptr;
116 static typename managed_shm::segment_manager::template construct_proxy<T>::type construct(const std::string &name);
117#endif
118 static T *find(const std::string &name);
119 static bool destroy(const std::string &name);
120 static T *find_and_ref(const std::string &name); // as find, but reference array
121 static bool destroy_array(const std::string &name, array_ptr arr);
122};
123
124template<class T>
125class shm_array_ref;
126template<class T>
128
130 template<typename T>
131 friend struct shm;
132 friend class Communicator;
133
134public:
135 static std::string instanceName(const std::string &host, unsigned short port);
136 static Shm &the();
137 static bool perRank();
138 static bool remove(const std::string &shmname, int moduleID, int rank, bool perRank);
139 static Shm &create(const std::string &shmname, int moduleID, int rank, bool perRank);
140 static Shm &attach(const std::string &shmname, int moduleID, int rank, bool perRank);
141 static bool isAttached();
142
143 void detach();
144 void setRemoveOnDetach();
145
146 std::string name() const;
147 const std::string &instanceName() const;
148 int owningRank() const;
149
150#ifdef NO_SHMEM
152#else
153 typedef boost::interprocess::allocator<void, managed_shm::segment_manager> void_allocator;
154 managed_shm &shm();
155 const managed_shm &shm() const;
156#endif
157 const void_allocator &allocator() const;
158
159 std::string createArrayId(const std::string &name = "");
160 std::string createObjectId(const std::string &name = "");
161
162 void lockObjects() const;
163 void unlockObjects() const;
164 void lockDictionary() const;
165 void unlockDictionary() const;
166
167 int objectID() const;
168 int arrayID() const;
169 void setObjectID(int id);
170 void setArrayID(int id);
171
172 std::shared_ptr<const Object> getObjectFromHandle(const shm_handle_t &handle) const;
173 shm_handle_t getHandleFromObject(std::shared_ptr<const Object> object) const;
174 shm_handle_t getHandleFromObject(const Object *object) const;
175 shm_handle_t getHandleFromArray(const ShmData *array) const;
176 ObjectData *getObjectDataFromName(const std::string &name) const;
177 ObjectData *getObjectDataFromHandle(const shm_handle_t &handle) const;
178 std::shared_ptr<const Object> getObjectFromName(const std::string &name, bool onlyComplete = true) const;
179 template<typename T>
180 const ShmVector<T> getArrayFromName(const std::string &name) const;
181
182 static std::string shmIdFilename();
183 static bool cleanAll(int rank);
184
185 void markAsRemoved(const std::string &name);
186 void addObject(const std::string &name, const shm_handle_t &handle);
187 void addArray(const std::string &name, const ShmData *array);
188#ifdef SHMDEBUG
189#ifdef NO_SHMEM
191 static std::recursive_mutex *s_shmdebugMutex;
192#else
194 static boost::interprocess::interprocess_recursive_mutex *s_shmdebugMutex;
195#endif
196#endif
197
198#ifdef SHMBARRIER
199 pthread_barrier_t *newBarrier(const std::string &name, int count);
200 void deleteBarrier(const std::string &name);
201#endif
202
203private:
204 // create on size>0, otherwise attach
205 Shm(const std::string &name, const int moduleID, const int rank, size_t size = 0);
206 ~Shm();
207
208 void setId(int id);
209
210 void_allocator *m_allocator;
211 std::string m_name;
212 bool m_remove;
213 int m_id;
214 const int m_rank;
215 int m_owningRank = -1;
216 std::atomic<int> m_objectId, m_arrayId;
217 static Shm *s_singleton;
218#ifdef NO_SHMEM
219 mutable std::recursive_mutex *m_shmDeletionMutex;
220 mutable std::recursive_mutex *m_objectDictionaryMutex;
221 std::map<std::string, shm_handle_t> m_objectDictionary;
222#else
223 static bool s_perRank;
224 mutable boost::interprocess::interprocess_recursive_mutex *m_shmDeletionMutex;
225 mutable boost::interprocess::interprocess_recursive_mutex *m_objectDictionaryMutex;
226 managed_shm *m_shm;
227#endif
228 mutable std::atomic<int> m_lockCount;
229#ifdef SHMBARRIER
230#ifndef NO_SHMEM
231 std::map<std::string, boost::interprocess::ipcdetail::barrier_initializer> m_barriers;
232#endif
233#endif
234};
235
236template<typename T>
237T *shm<T>::find(const std::string &name)
238{
239#ifdef NO_SHMEM
241 auto &dict = Shm::the().m_objectDictionary;
242 auto it = dict.find(name);
243 if (it == dict.end()) {
245 return nullptr;
246 }
248 return static_cast<T *>(it->second);
249#else
250 return Shm::the().shm().find<T>(name.c_str()).first;
251#endif
252}
253
254template<typename T>
255T *shm<T>::find_and_ref(const std::string &name)
256{
257#ifdef NO_SHMEM
259 T *t = shm<T>::find(name);
260 if (t)
261 t->ref();
263 return t;
264#else
266 T *t = shm<T>::find(name);
267 if (t) {
268 t->ref();
269 assert(t->refcount() > 0);
270 }
272 return t;
273#endif
274}
275
276template<typename T>
277bool shm<T>::destroy(const std::string &name)
278{
279#ifdef NO_SHMEM
281 auto &dict = Shm::the().m_objectDictionary;
282 auto it = dict.find(name);
283 bool ret = true;
284 if (it == dict.end()) {
286 std::cerr << "WARNING: shm: did not find object " << name << " to be deleted" << std::endl;
287 ret = false;
288 } else {
289 T *t = static_cast<T *>(it->second);
290 dict.erase(it);
292 delete t;
293 }
294#else
295 const bool ret = Shm::the().shm().destroy<T>(name.c_str());
296#endif
297 Shm::the().markAsRemoved(name);
298 return ret;
299}
300
301template<typename T>
302bool shm<T>::destroy_array(const std::string &name, shm<T>::array_ptr arr)
303{
304#ifdef NO_SHMEM
306 if (arr->refcount() > 0) {
308 return true;
309 }
310 bool ret = shm<shm<T>::array>::destroy(name);
312 return ret;
313#else
315 if (arr->refcount() > 0) {
317 return true;
318 }
319 assert(arr->refcount() == 0);
320 bool ret = shm<shm<T>::array>::destroy(name);
322 return ret;
323#endif
324}
325
326#ifdef NO_SHMEM
327template<typename T>
328shm<T>::Constructor::Constructor(const std::string &name): name(name)
329{
331}
332
333template<typename T>
334shm<T>::Constructor::~Constructor()
335{
337}
338
339template<typename T>
340template<typename... Args>
341T *shm<T>::Constructor::operator()(Args &&...args)
342{
343 auto &dict = Shm::the().m_objectDictionary;
344 auto it = dict.find(name);
345 if (it != dict.end()) {
346 std::cerr << "WARNING: shm: already have " << name << std::endl;
347 return reinterpret_cast<T *>(it->second);
348 }
349
350 T *t = new T(std::forward<Args>(args)...);
351 dict[name] = t;
352 return t;
353}
354#endif
355
356} // namespace vistle
357
358#endif
359
360#include "shm_reference.h"
361
362namespace vistle {
363//using ShmVector = shm_array_ref<shm_array<T, typename shm<T>::allocator>>;
364
365
366}
367
368#include "shm_impl.h"
Definition: object.h:58
Definition: shm.h:129
friend struct shm
Definition: shm.h:131
void unlockObjects() const
Definition: shm.cpp:203
static Shm & the()
Definition: shm.cpp:315
void lockObjects() const
Definition: shm.cpp:191
boost::interprocess::allocator< void, managed_shm::segment_manager > void_allocator
Definition: shm.h:153
void unlockDictionary() const
Definition: shm.cpp:222
shm_handle_t getHandleFromObject(std::shared_ptr< const Object > object) const
void markAsRemoved(const std::string &name)
Definition: shm.cpp:481
void lockDictionary() const
Definition: shm.cpp:215
Definition: allocator.h:12
Definition: exception.h:13
Definition: shm_reference.h:15
Definition: shm_array.h:19
Definition: shm.h:67
shm_exception(const std::string &what="shared memory error")
Definition: shm.h:69
#define V_COREEXPORT
Definition: export.h:9
Definition: allobjects.cpp:30
boost::interprocess::managed_shared_memory managed_shm
Definition: shm.h:57
managed_shm::handle_t shm_handle_t
Definition: object.h:40
default_init_allocator< T > allocator
Definition: allocator.h:36
Definition: object.h:233
Definition: shmdata.h:12
Definition: shm.h:94
static T * find(const std::string &name)
Definition: shm.h:237
boost::interprocess::offset_ptr< array > array_ptr
Definition: shm.h:115
static bool destroy_array(const std::string &name, array_ptr arr)
Definition: shm.h:302
static T * find_and_ref(const std::string &name)
Definition: shm.h:255
static bool destroy(const std::string &name)
Definition: shm.h:277
boost::interprocess::basic_string< T, std::char_traits< T >, allocator > string
Definition: shm.h:112
boost::interprocess::allocator< T, managed_shm::segment_manager > allocator
Definition: shm.h:111
boost::interprocess::vector< T, allocator > vector
Definition: shm.h:113
vistle::shm_array< T, allocator > array
Definition: shm.h:114
static managed_shm::segment_manager::template construct_proxy< T >::type construct(const std::string &name)
Definition: shm_impl.h:87