SharedMemoryConsumer.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package VisionX::Core
19 * @author Kai Welke (kai dot welke at kit dot edu)
20 * @date 2012
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#pragma once
26
27// boost
28#include <memory>
29#ifndef Q_MOC_RUN
30#include <boost/interprocess/managed_shared_memory.hpp>
31#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
32#include <boost/interprocess/sync/sharable_lock.hpp>
33#endif
34
35// exceptions
36#include <iostream>
37
39#include <ArmarXCore/interface/core/SharedMemory.h>
40
41namespace armarx
42{
44 boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex>;
45 using SharedMemoryScopedReadLockPtr = std::shared_ptr<SharedMemoryScopedReadLock>;
46
47 /**
48 * \class SharedMemoryConsumer
49 * \ingroup SharedMemory
50 * The SharedMemoryConsumer opens an existing shared memory segment for reading. It provides synchronized read access to the
51 * shared data. The memory content is an array of objects, where the object type is specified as template parameter.
52 * The SharedMemoryConsumer needs to be constructed, after a SharedMemoryProvider has been created.
53 */
54 template <class MemoryObject, class MemoryObjectMetaInfo = MetaInfoSizeBase>
56 {
57 public:
58 class Wrapper : public MemoryObjectMetaInfo
59 {
60 public:
62 {
63 }
64
65 Wrapper(const MemoryObjectMetaInfo& source) : MemoryObjectMetaInfo(source)
66 {
67 }
68 };
69
70 /**
71 * Creates a shared memory consumer.
72 *
73 * @param memoryName name of the memory as set in the SharedMemoryProvider
74 *
75 * @throw SharedMemoryConnectionFailure
76 */
77 SharedMemoryConsumer(std::string newMemoryName)
78 {
79
80 this->memoryName = newMemoryName;
81 auto env_c_str = getenv("USER");
82 std::string userName = env_c_str ? env_c_str : "";
83
84 if (!userName.empty())
85 {
86 this->memoryName += userName;
87 }
88
89 // create shared memory segment
90 try
91 {
92 sharedMemorySegment = new boost::interprocess::managed_shared_memory(
93 boost::interprocess::open_only, memoryName.c_str());
94 }
95 catch (const boost::interprocess::interprocess_exception& e)
96 {
97 std::string reason = "Error opening shared memory segment for reading: ";
99 reason + e.what());
100 }
101
102 info = sharedMemorySegment->find<Wrapper>("Info").first;
103
104 if (!info)
105 {
107 memoryName, "Error opening memory size for reading");
108 }
109
110 // get or create the shared image mutex
111 memoryMutex =
112 sharedMemorySegment
113 ->find<boost::interprocess::interprocess_upgradable_mutex>("SharedMutex")
114 .first;
115
116 if (!memoryMutex)
117 {
119 memoryName, "Error opening shared mutex for reading");
120 }
121
122 // create the managed image memory object
123 data = sharedMemorySegment->find<MemoryObject>("Data").first;
124
125 if (!data)
126 {
128 memoryName, "Error opening shared data for reading");
129 }
130
131 condSizeChanged =
132 sharedMemorySegment
133 ->find<boost::interprocess::interprocess_condition>("CondSizeChanged")
134 .first;
135
136 if (!data)
137 {
139 memoryName, "Error opening condition variable for reading");
140 }
141 }
142
143 /**
144 * Destructs the shared memory consumer.
145 */
147 {
148 // removing of shared memory disabled since otherwise reopening fails
149 //boost::interprocess::shared_memory_object::remove(memoryName.c_str());
150 }
151
152 /**
153 * Retrieve size of usable shared memory.
154 *
155 * @return size in bytes
156 */
157 int
158 getSize() const
159 {
161 if (!info)
162 {
164 memoryName, "Error opening shared mutex for reading");
165 }
166
167 return info->size;
168 }
169
170 typename MemoryObjectMetaInfo::PointerType
171 getMetaInfo(bool threadSafe = true) const
172 {
174 if (threadSafe)
175 {
177 }
178 if (info)
179 {
180 return new Wrapper(*info);
181 }
182 else
183 {
184 return NULL;
185 }
186 }
187
188 /**
189 * Retrieve pointer to shared memory. Use getScopedReadLock() or lock() / unlock() before reading from the memory.
190 *
191 * @return pointer to the shared memory with type MemoryObject
192 */
193 MemoryObject*
195 {
196 return data;
197 }
198
199 /**
200 * Retrieve scoped lock to the shared memory for reading.
201 *
202 * @return scoped lock to shared memory
203 */
206 {
208
209 if (memoryMutex)
210 {
211 lock.reset(new SharedMemoryScopedReadLock(*memoryMutex));
212 }
213
214 return lock;
215 }
216
217 /**
218 * Lock shared memory for reading.
219 */
220 void
222 {
223 if (memoryMutex)
224 {
225 memoryMutex->lock_sharable();
226 }
227 }
228
229 /**
230 * Unlock shared memory after reading.
231 */
232 void
234 {
235 if (memoryMutex)
236 {
237 memoryMutex->unlock_sharable();
238 }
239 }
240
241 /**
242 * Pointer type for convenience.
243 */
245 std::shared_ptr<SharedMemoryConsumer<MemoryObject, MemoryObjectMetaInfo>>;
246
247 private:
248 /**
249 * Name of memory segment
250 */
251 std::string memoryName;
252
253 /**
254 * Managed shared memory segment
255 */
256 boost::interprocess::managed_shared_memory* sharedMemorySegment;
257
258 /**
259 * Upgradable data mutex
260 */
261 mutable boost::interprocess::interprocess_upgradable_mutex* memoryMutex;
262
263 /**
264 * @brief condSizeChanged whether the size was changed
265 */
266 boost::interprocess::interprocess_condition* condSizeChanged;
267
268 /**
269 * the data
270 */
271 MemoryObject* data;
272
273 MemoryObjectMetaInfo* info;
274 };
275} // namespace armarx
Wrapper(const MemoryObjectMetaInfo &source)
MemoryObjectMetaInfo::PointerType getMetaInfo(bool threadSafe=true) const
SharedMemoryScopedReadLockPtr getScopedReadLock() const
Retrieve scoped lock to the shared memory for reading.
MemoryObject * getMemory()
Retrieve pointer to shared memory.
int getSize() const
Retrieve size of usable shared memory.
void unlock()
Unlock shared memory after reading.
void lock()
Lock shared memory for reading.
std::shared_ptr< SharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
~SharedMemoryConsumer()
Destructs the shared memory consumer.
SharedMemoryConsumer(std::string newMemoryName)
Creates a shared memory consumer.
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< SharedMemoryScopedReadLock > SharedMemoryScopedReadLockPtr
boost::interprocess::sharable_lock< boost::interprocess::interprocess_upgradable_mutex > SharedMemoryScopedReadLock