SHM
Shared-memorybasedHandy-communicationManager
shm_pub_sub.hpp
Go to the documentation of this file.
1 
15 #ifndef __SHM_PS_LIB_H__
16 #define __SHM_PS_LIB_H__
17 
18 #include <iostream>
19 #include <limits>
20 #include <string>
21 #include <regex>
22 #include <stdexcept>
23 #include <mutex>
24 extern "C" {
25 #include <sys/mman.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <sys/time.h>
29 #include <pthread.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/ipc.h>
33 #include <sys/shm.h>
34 }
35 #include "shm_base.hpp"
36 
37 namespace irlab
38 {
39 
40 namespace shm
41 {
42 
43 // ****************************************************************************
57 // ****************************************************************************
58 template <typename T>
59 class Publisher
60 {
61 public:
62  Publisher(std::string name = "", int buffer_num = 3, PERM perm = DEFAULT_PERM, bool legacy = false);
63  ~Publisher();
64 
65  void publish(const T& data);
66 
67 private:
68  std::string shm_name;
69  int shm_buf_num;
70  PERM shm_perm;
71  SharedMemory *shared_memory;
72  RingBuffer *ring_buffer;
73 
74  size_t data_size;
75 
76  //For legacy system
77  uint8_t *data_ptr;
78  bool is_legacy;
79 };
80 
81 // ****************************************************************************
89 // ****************************************************************************
90 template <typename T>
92 {
93 public:
94  Subscriber(std::string name = "", bool legacy = false);
95  ~Subscriber();
96 
97  const T subscribe(bool *state);
98  bool waitFor(uint64_t timeout_usec);
99  void setDataExpiryTime_us(uint64_t time_us);
100 
101 private:
102  std::string shm_name;
103  SharedMemory *shared_memory;
104  RingBuffer *ring_buffer;
105  int current_reading_buffer;
106  uint64_t data_expiry_time_us;
107 
108  //For legacy system
109  uint8_t *data_ptr;
110  bool is_legacy;
111 };
112 
113 // ****************************************************************************
114 // Function Definications
115 // 関数定義
116 // (テンプレートクラス内の関数の定義はコンパイル時に実体化するのでヘッダに書く)
117 // ****************************************************************************
118 
131 template <typename T>
132 Publisher<T>::Publisher(std::string name, int buffer_num, PERM perm, bool legacy)
133 : shm_name(name)
134 , shm_buf_num(buffer_num)
135 , shm_perm(perm)
136 , shared_memory(nullptr)
137 , ring_buffer(nullptr)
138 , data_size(sizeof(T))
139 , data_ptr(nullptr)
140 , is_legacy(legacy)
141 {
142  if (!std::is_standard_layout<T>::value)
143  {
144  throw std::runtime_error("shm::Publisher: Be setted not POD class!");
145  }
146 
147  if (name.empty())
148  {
149  throw std::runtime_error("shm::Publisher: Please set name!");
150  }
151 
152  shared_memory = new SharedMemoryPosix(shm_name, O_RDWR|O_CREAT, shm_perm);
153  if (!is_legacy)
154  {
155  shared_memory->connect(RingBuffer::getSize(sizeof(T), shm_buf_num));
156  }
157  else
158  {
159  shared_memory->connect(sizeof(T));
160  }
161  if (shared_memory->isDisconnected())
162  {
163  throw std::runtime_error("shm::Publisher: Cannot get memory!");
164  }
165 
166  if (!is_legacy)
167  {
168  ring_buffer = new RingBuffer(shared_memory->getPtr(), sizeof(T), shm_buf_num);
169  }
170  else
171  {
172  data_ptr = shared_memory->getPtr();
173  }
174 }
175 
176 
183 template <typename T>
185 {
186  if (ring_buffer != nullptr)
187  {
188  delete ring_buffer;
189  }
190  if (shared_memory != nullptr)
191  {
192  delete shared_memory;
193  }
194 }
195 
205 template <typename T>
206 void
207 Publisher<T>::publish(const T& data)
208 {
209 /*
210  if (data_size != sizeof(T))
211  {
212  delete ring_buffer;
213  ring_buffer = nullptr;
214  shared_memory->disconnect();
215  shared_memory->connect(RingBuffer::getSize(sizeof(T), shm_buf_num));
216  ring_buffer = new RingBuffer(shared_memory->getPtr(), sizeof(T), shm_buf_num);
217  }
218 */
219  if (!is_legacy)
220  {
221  int oldest_buffer = ring_buffer->getOldestBufferNum();
222 
223  (reinterpret_cast<T *>(ring_buffer->getDataList()))[oldest_buffer] = data;
224 
225  struct timespec t;
226  clock_gettime(CLOCK_MONOTONIC_RAW, &t);
227  ring_buffer->setTimestamp_us(((uint64_t) t.tv_sec * 1000000L) + ((uint64_t) t.tv_nsec / 1000L), oldest_buffer);
228 
229  ring_buffer->signal();
230  }
231  else
232  {
233  memcpy(data_ptr, &data, sizeof(T));
234  }
235 }
236 
237 
246 template <typename T>
247 Subscriber<T>::Subscriber(std::string name, bool legacy)
248 : shm_name(name)
249 , shared_memory(nullptr)
250 , ring_buffer(nullptr)
251 , current_reading_buffer(0)
252 , data_expiry_time_us(2000000)
253 , data_ptr(nullptr)
254 , is_legacy(legacy)
255 {
256  if (!std::is_standard_layout<T>::value)
257  {
258  throw std::runtime_error("shm::Subscriber: Be setted not POD class!");
259  }
260 
261  if (name.empty())
262  {
263  throw std::runtime_error("shm::Subscriber: Please set name!");
264  }
265 
266  shared_memory = new SharedMemoryPosix(shm_name, O_RDWR, static_cast<PERM>(0));
267 }
268 
269 
276 template <typename T>
278 {
279  if (ring_buffer != nullptr)
280  {
281  delete ring_buffer;
282  }
283  if (shared_memory != nullptr)
284  {
285  delete shared_memory;
286  }
287 }
288 
289 
299 template <typename T>
300 const T
301 Subscriber<T>::subscribe(bool *is_success)
302 {
303  if (!is_legacy)
304  {
305  if (shared_memory->isDisconnected())
306  {
307  if (ring_buffer != nullptr)
308  {
309  delete ring_buffer;
310  ring_buffer = nullptr;
311  }
312  shared_memory->connect();
313  if (shared_memory->isDisconnected())
314  {
315  *is_success = false;
316  return T();
317  }
318  ring_buffer = new RingBuffer(shared_memory->getPtr());
319  ring_buffer->setDataExpiryTime_us(data_expiry_time_us);
320  }
321  int newest_buffer = ring_buffer->getNewestBufferNum();
322  if (newest_buffer < 0)
323  {
324  *is_success = false;
325  return (reinterpret_cast<T*>(ring_buffer->getDataList()))[current_reading_buffer];
326  }
327  *is_success = true;
328  current_reading_buffer = newest_buffer;
329  return (reinterpret_cast<T*>(ring_buffer->getDataList()))[current_reading_buffer];
330  }
331  else
332  {
333  if (shared_memory->isDisconnected())
334  {
335  shared_memory->connect();
336  if (shared_memory->isDisconnected())
337  {
338  *is_success = false;
339  return T();
340  }
341  data_ptr = shared_memory->getPtr();
342  }
343  *is_success = true;
344  return *reinterpret_cast<T*>(data_ptr);
345  }
346 }
347 
348 
349 template <typename T>
350 bool
351 Subscriber<T>::waitFor(uint64_t timeout_usec)
352 {
353  if (is_legacy)
354  {
355  return false;
356  }
357 
358  if (shared_memory->isDisconnected())
359  {
360  if (ring_buffer != nullptr)
361  {
362  delete ring_buffer;
363  ring_buffer = nullptr;
364  }
365  shared_memory->connect();
366  if (shared_memory->isDisconnected())
367  {
368  return false;
369  }
370  ring_buffer = new RingBuffer(shared_memory->getPtr());
371  ring_buffer->setDataExpiryTime_us(data_expiry_time_us);
372  }
373 
374  return ring_buffer->waitFor(timeout_usec);
375 }
376 
377 
378 template <typename T>
379 void
380 Subscriber<T>::setDataExpiryTime_us(uint64_t time_us)
381 {
382  data_expiry_time_us = time_us;
383  if (ring_buffer != nullptr)
384  {
385  ring_buffer->setDataExpiryTime_us(data_expiry_time_us);
386  }
387 }
388 
389 
390 }
391 
392 }
393 
394 #endif /* __SHM_PS_LIB_H__ */
shm_base.hpp
Basic class definitions for accessing shared memory, ring buffers, etc. The notation is complianted R...
irlab::shm::Subscriber
Class representing a subscriber that retrieves topics from shared memory This class is used to load a...
Definition: shm_pub_sub.hpp:91
irlab::shm::Publisher::publish
void publish(const T &data)
Publish a topic None Writes the topic to the buffer with the oldest timestamp and updates the timesta...
Definition: shm_pub_sub.hpp:207
irlab::shm::PERM
PERM
Definition: shm_base.hpp:40
irlab::shm::SharedMemory
Class that abstracts the method of accessing shared memory.
Definition: shm_base.hpp:84
irlab::shm::Subscriber::Subscriber
Subscriber(std::string name="", bool legacy=false)
Constructor Shared-memory name None Access to shared memory.
Definition: shm_pub_sub.hpp:247
irlab::shm::Subscriber::~Subscriber
~Subscriber()
Destructor None Release the secured local members.
Definition: shm_pub_sub.hpp:277
irlab::shm::Subscriber::subscribe
const T subscribe(bool *state)
Subscribe a topic Const reference to the loaded topic. The topic with the most recent timestamp is lo...
Definition: shm_pub_sub.hpp:301
irlab::shm::SharedMemoryPosix
Class that is described the method of accessing POSIX shared memory.
Definition: shm_base.hpp:112
irlab::shm::Publisher::Publisher
Publisher(std::string name="", int buffer_num=3, PERM perm=DEFAULT_PERM, bool legacy=false)
Constructor Shared-memory name Number of Buffers Permission infomation None Create shared memory obje...
Definition: shm_pub_sub.hpp:132
irlab::shm::Publisher
Class representing a publisher that outputs topics to shared memory This class is used to output the ...
Definition: shm_pub_sub.hpp:59
irlab::shm::RingBuffer
Class that is described ring-buffer used for shared memory.
Definition: shm_base.hpp:135
irlab::shm::Publisher::~Publisher
~Publisher()
Destructor None
Definition: shm_pub_sub.hpp:184