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/sharable_lock.hpp>
32 #include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
33 #endif
34 
35 // exceptions
37 #include <ArmarXCore/interface/core/SharedMemory.h>
38 #include <iostream>
39 
40 namespace armarx
41 {
42  using SharedMemoryScopedReadLock = boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> ;
43  using SharedMemoryScopedReadLockPtr = std::shared_ptr<SharedMemoryScopedReadLock>;
44 
45  /**
46  * \class SharedMemoryConsumer
47  * \ingroup SharedMemory
48  * The SharedMemoryConsumer opens an existing shared memory segment for reading. It provides synchronized read access to the
49  * shared data. The memory content is an array of objects, where the object type is specified as template parameter.
50  * The SharedMemoryConsumer needs to be constructed, after a SharedMemoryProvider has been created.
51  */
52  template <class MemoryObject, class MemoryObjectMetaInfo = MetaInfoSizeBase>
54  {
55  public:
56 
57 
58 
59  class Wrapper : public MemoryObjectMetaInfo
60  {
61  public:
62  Wrapper() {}
63  Wrapper(const MemoryObjectMetaInfo& source) : MemoryObjectMetaInfo(source) {}
64  };
65 
66 
67  /**
68  * Creates a shared memory consumer.
69  *
70  * @param memoryName name of the memory as set in the SharedMemoryProvider
71  *
72  * @throw SharedMemoryConnectionFailure
73  */
74  SharedMemoryConsumer(std::string newMemoryName)
75  {
76 
77  this->memoryName = newMemoryName;
78  auto env_c_str = getenv("USER");
79  std::string userName = env_c_str ? env_c_str : "";
80 
81  if (!userName.empty())
82  {
83  this->memoryName += userName;
84  }
85 
86  // create shared memory segment
87  try
88  {
89  sharedMemorySegment = new boost::interprocess::managed_shared_memory(boost::interprocess::open_only, memoryName.c_str());
90  }
91  catch (const boost::interprocess::interprocess_exception& e)
92  {
93  std::string reason = "Error opening shared memory segment for reading: ";
94  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, reason + e.what());
95  }
96 
97  info = sharedMemorySegment->find<Wrapper>("Info").first;
98 
99  if (!info)
100  {
101  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error opening memory size for reading");
102  }
103 
104  // get or create the shared image mutex
105  memoryMutex = sharedMemorySegment->find<boost::interprocess::interprocess_upgradable_mutex>("SharedMutex").first;
106 
107  if (!memoryMutex)
108  {
109  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error opening shared mutex for reading");
110  }
111 
112  // create the managed image memory object
113  data = sharedMemorySegment->find<MemoryObject>("Data").first;
114 
115  if (!data)
116  {
117  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error opening shared data for reading");
118  }
119 
120  condSizeChanged = sharedMemorySegment->find<boost::interprocess::interprocess_condition>("CondSizeChanged").first;
121 
122  if (!data)
123  {
124  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error opening condition variable for reading");
125  }
126  }
127 
128  /**
129  * Destructs the shared memory consumer.
130  */
132  {
133  // removing of shared memory disabled since otherwise reopening fails
134  //boost::interprocess::shared_memory_object::remove(memoryName.c_str());
135  }
136 
137  /**
138  * Retrieve size of usable shared memory.
139  *
140  * @return size in bytes
141  */
142  int getSize() const
143  {
145  if (!info)
146  {
147  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error opening shared mutex for reading");
148  }
149 
150  return info->size;
151  }
152 
153  typename MemoryObjectMetaInfo::PointerType getMetaInfo(bool threadSafe = true) const
154  {
156  if (threadSafe)
157  {
159  }
160  if (info)
161  {
162  return new Wrapper(*info);
163  }
164  else
165  {
166  return NULL;
167  }
168  }
169 
170 
171  /**
172  * Retrieve pointer to shared memory. Use getScopedReadLock() or lock() / unlock() before reading from the memory.
173  *
174  * @return pointer to the shared memory with type MemoryObject
175  */
176  MemoryObject* getMemory()
177  {
178  return data;
179  }
180 
181  /**
182  * Retrieve scoped lock to the shared memory for reading.
183  *
184  * @return scoped lock to shared memory
185  */
187  {
189 
190  if (memoryMutex)
191  {
192  lock.reset(new SharedMemoryScopedReadLock(*memoryMutex));
193  }
194 
195  return lock;
196  }
197 
198  /**
199  * Lock shared memory for reading.
200  */
201  void lock()
202  {
203  if (memoryMutex)
204  {
205  memoryMutex->lock_sharable();
206  }
207  }
208 
209  /**
210  * Unlock shared memory after reading.
211  */
212  void unlock()
213  {
214  if (memoryMutex)
215  {
216  memoryMutex->unlock_sharable();
217  }
218  }
219 
220  /**
221  * Pointer type for convenience.
222  */
223  using pointer_type = std::shared_ptr<SharedMemoryConsumer<MemoryObject, MemoryObjectMetaInfo> >;
224 
225  private:
226  /**
227  * Name of memory segment
228  */
229  std::string memoryName;
230 
231  /**
232  * Managed shared memory segment
233  */
234  boost::interprocess::managed_shared_memory* sharedMemorySegment;
235 
236  /**
237  * Upgradable data mutex
238  */
239  mutable boost::interprocess::interprocess_upgradable_mutex* memoryMutex;
240 
241  /**
242  * @brief condSizeChanged whether the size was changed
243  */
244  boost::interprocess::interprocess_condition* condSizeChanged;
245 
246  /**
247  * the data
248  */
249  MemoryObject* data;
250 
251  MemoryObjectMetaInfo* info;
252  };
253 }
254 
armarx::SharedMemoryConsumer
Definition: SharedMemoryConsumer.h:53
armarx::SharedMemoryConsumer::unlock
void unlock()
Unlock shared memory after reading.
Definition: SharedMemoryConsumer.h:212
armarx::SharedMemoryConsumer::SharedMemoryConsumer
SharedMemoryConsumer(std::string newMemoryName)
Creates a shared memory consumer.
Definition: SharedMemoryConsumer.h:74
armarx::SharedMemoryConsumer::Wrapper::Wrapper
Wrapper(const MemoryObjectMetaInfo &source)
Definition: SharedMemoryConsumer.h:63
armarx::SharedMemoryScopedReadLockPtr
std::shared_ptr< SharedMemoryScopedReadLock > SharedMemoryScopedReadLockPtr
Definition: SharedMemoryConsumer.h:43
armarx::SharedMemoryConsumer::Wrapper
Definition: SharedMemoryConsumer.h:59
armarx::exceptions::local::SharedMemoryConnectionFailure
Definition: SharedMemoryExceptions.h:49
armarx::SharedMemoryConsumer::getMemory
MemoryObject * getMemory()
Retrieve pointer to shared memory.
Definition: SharedMemoryConsumer.h:176
armarx::SharedMemoryConsumer::pointer_type
std::shared_ptr< SharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
Pointer type for convenience.
Definition: SharedMemoryConsumer.h:223
armarx::SharedMemoryConsumer::getMetaInfo
MemoryObjectMetaInfo::PointerType getMetaInfo(bool threadSafe=true) const
Definition: SharedMemoryConsumer.h:153
boost::source
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:681
armarx::SharedMemoryConsumer::getSize
int getSize() const
Retrieve size of usable shared memory.
Definition: SharedMemoryConsumer.h:142
armarx::SharedMemoryScopedReadLock
boost::interprocess::sharable_lock< boost::interprocess::interprocess_upgradable_mutex > SharedMemoryScopedReadLock
Definition: SharedMemoryConsumer.h:42
SharedMemoryExceptions.h
armarx::SharedMemoryConsumer::getScopedReadLock
SharedMemoryScopedReadLockPtr getScopedReadLock() const
Retrieve scoped lock to the shared memory for reading.
Definition: SharedMemoryConsumer.h:186
armarx::SharedMemoryConsumer::~SharedMemoryConsumer
~SharedMemoryConsumer()
Destructs the shared memory consumer.
Definition: SharedMemoryConsumer.h:131
armarx::SharedMemoryConsumer::Wrapper::Wrapper
Wrapper()
Definition: SharedMemoryConsumer.h:62
armarx::SharedMemoryConsumer::lock
void lock()
Lock shared memory for reading.
Definition: SharedMemoryConsumer.h:201
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28