13 #ifndef __SHM_ACTION_LIB_H__
14 #define __SHM_ACTION_LIB_H__
26 enum ACTION_STATUS : uint8_t
47 template <
class Goal,
class Result,
class Feedback>
54 void waitNewGoalAvailable();
58 bool isPreemptRequested();
61 void publishResult(
const Result& result);
62 void publishFeedback(
const Feedback& feedback);
65 void initializeExclusiveAccess();
73 uint64_t start_timestamp_us;
77 pthread_mutex_t *goal_mutex;
78 pthread_cond_t *goal_condition;
79 uint64_t *goal_timestamp_us;
81 pthread_mutex_t *result_mutex;
82 pthread_cond_t *result_condition;
83 uint64_t *result_timestamp_us;
85 Feedback *feedback_ptr;
86 ACTION_STATUS *status_ptr;
87 uint64_t *cancel_timestamp_us;
89 uint64_t current_goal_timestamp_usec;
98 template <
class Goal,
class Result,
class Feedback>
107 Feedback getFeedback();
108 ACTION_STATUS getStatus();
109 bool isServerConnected();
110 bool sendGoal(Goal goal);
111 bool waitForResult(
unsigned long wait_time_us);
112 bool waitForServer(
unsigned long wait_time_us);
115 std::string shm_name;
120 pthread_mutex_t *goal_mutex;
121 pthread_cond_t *goal_condition;
122 uint64_t *goal_timestamp_us;
124 pthread_mutex_t *result_mutex;
125 pthread_cond_t *result_condition;
126 uint64_t *result_timestamp_us;
128 Feedback *feedback_ptr;
129 ACTION_STATUS *status_ptr;
130 uint64_t *cancel_timestamp_us;
132 uint64_t current_result_timestamp_usec;
139 template <
class Goal,
class Result,
class Feedback>
143 , shared_memory(nullptr)
144 , memory_ptr(nullptr)
146 if (!std::is_standard_layout<Goal>::value
147 || !std::is_standard_layout<Result>::value
148 || !std::is_standard_layout<Feedback>::value)
150 throw std::runtime_error(
"shm::ActionServer: Be setted not POD class!");
153 shared_memory =
new SharedMemoryPosix(shm_name, O_RDWR|O_CREAT, shm_perm);
154 shared_memory->connect( (
sizeof(pthread_mutex_t)+
sizeof(pthread_cond_t)+
sizeof(uint64_t)) * 2 +
sizeof(Goal) +
sizeof(Result) +
sizeof(Feedback) +
sizeof(ACTION_STATUS) +
sizeof(uint64_t));
155 if (shared_memory->isDisconnected())
157 throw std::runtime_error(
"shm::ActionServer: Cannot get memory!");
160 uint8_t *data_ptr = shared_memory->getPtr();
161 memory_ptr = data_ptr;
162 goal_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
163 data_ptr +=
sizeof(pthread_mutex_t);
164 goal_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
165 data_ptr +=
sizeof(pthread_cond_t);
166 goal_timestamp_us =
reinterpret_cast<uint64_t *
>(data_ptr);
167 data_ptr +=
sizeof(uint64_t);
168 goal_ptr =
reinterpret_cast<Goal *
>(data_ptr);
169 data_ptr +=
sizeof(Goal);
170 result_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
171 data_ptr +=
sizeof(pthread_mutex_t);
172 result_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
173 data_ptr +=
sizeof(pthread_cond_t);
174 result_timestamp_us =
reinterpret_cast<uint64_t *
>(data_ptr);
175 data_ptr +=
sizeof(uint64_t);
176 result_ptr =
reinterpret_cast<Result *
>(data_ptr);
177 data_ptr +=
sizeof(Result);
178 feedback_ptr =
reinterpret_cast<Feedback *
>(data_ptr);
179 data_ptr +=
sizeof(Feedback);
180 status_ptr =
reinterpret_cast<ACTION_STATUS *
>(data_ptr);
181 data_ptr +=
sizeof(ACTION_STATUS);
182 cancel_timestamp_us =
reinterpret_cast<uint64_t *
>(data_ptr);
184 initializeExclusiveAccess();
186 *status_ptr = SUCCEEDED;
189 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
190 *cancel_timestamp_us = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
191 start_timestamp_us = *cancel_timestamp_us;
192 *goal_timestamp_us = *cancel_timestamp_us;
193 *result_timestamp_us = *cancel_timestamp_us;
195 current_goal_timestamp_usec = *goal_timestamp_us;
198 template <
class Goal,
class Result,
class Feedback>
199 ActionServer<Goal, Result, Feedback>::~ActionServer()
201 shared_memory->disconnect();
202 if (shared_memory !=
nullptr)
204 delete shared_memory;
208 template <
class Goal,
class Result,
class Feedback>
210 ActionServer<Goal, Result, Feedback>::initializeExclusiveAccess()
212 pthread_condattr_t goal_cond_attr;
213 pthread_condattr_init(&goal_cond_attr);
214 pthread_condattr_setpshared(&goal_cond_attr, PTHREAD_PROCESS_SHARED);
215 pthread_cond_init(goal_condition, &goal_cond_attr);
216 pthread_condattr_destroy(&goal_cond_attr);
218 pthread_mutexattr_t goal_m_attr;
219 pthread_mutexattr_init(&goal_m_attr);
220 pthread_mutexattr_setpshared(&goal_m_attr, PTHREAD_PROCESS_SHARED);
221 pthread_mutex_init(goal_mutex, &goal_m_attr);
222 pthread_mutexattr_destroy(&goal_m_attr);
224 pthread_condattr_t result_cond_attr;
225 pthread_condattr_init(&result_cond_attr);
226 pthread_condattr_setpshared(&result_cond_attr, PTHREAD_PROCESS_SHARED);
227 pthread_cond_init(result_condition, &result_cond_attr);
228 pthread_condattr_destroy(&result_cond_attr);
230 pthread_mutexattr_t result_m_attr;
231 pthread_mutexattr_init(&result_m_attr);
232 pthread_mutexattr_setpshared(&result_m_attr, PTHREAD_PROCESS_SHARED);
233 pthread_mutex_init(result_mutex, &result_m_attr);
234 pthread_mutexattr_destroy(&result_m_attr);
237 template <
class Goal,
class Result,
class Feedback>
239 ActionServer<Goal, Result, Feedback>::waitNewGoalAvailable()
242 pthread_mutex_lock(goal_mutex);
243 while (current_goal_timestamp_usec >= *goal_timestamp_us)
246 pthread_cond_wait(goal_condition, goal_mutex);
248 pthread_mutex_unlock(goal_mutex);
251 template <
class Goal,
class Result,
class Feedback>
253 ActionServer<Goal, Result, Feedback>::acceptNewGoal()
255 pthread_mutex_lock(goal_mutex);
256 *status_ptr = ACTIVE;
258 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
259 start_timestamp_us = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
260 current_goal_timestamp_usec = *goal_timestamp_us;
261 Goal goal_copy = *goal_ptr;
262 pthread_mutex_unlock(goal_mutex);
267 template <
class Goal,
class Result,
class Feedback>
269 ActionServer<Goal, Result, Feedback>::rejectNewGoal()
271 *status_ptr = REJECTED;
272 current_goal_timestamp_usec = *goal_timestamp_us;
273 pthread_cond_broadcast(result_condition);
276 template <
class Goal,
class Result,
class Feedback>
278 ActionServer<Goal, Result, Feedback>::isPreemptRequested()
280 if (start_timestamp_us < *cancel_timestamp_us)
287 template <
class Goal,
class Result,
class Feedback>
289 ActionServer<Goal, Result, Feedback>::setPreempted()
291 *status_ptr = PREEMPTED;
294 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
295 *result_timestamp_us = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
297 pthread_cond_broadcast(result_condition);
300 template <
class Goal,
class Result,
class Feedback>
302 ActionServer<Goal, Result, Feedback>::publishResult(
const Result& result)
304 pthread_mutex_lock(result_mutex);
305 *result_ptr = result;
306 *status_ptr = SUCCEEDED;
309 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
310 *result_timestamp_us = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
311 pthread_mutex_unlock(result_mutex);
313 pthread_cond_broadcast(result_condition);
316 template <
class Goal,
class Result,
class Feedback>
318 ActionServer<Goal, Result, Feedback>::publishFeedback(
const Feedback& feedback)
321 pthread_mutex_lock(result_mutex);
322 *feedback_ptr = feedback;
323 pthread_mutex_unlock(result_mutex);
327 template <
class Goal,
class Result,
class Feedback>
328 ActionClient<Goal, Result, Feedback>::ActionClient(std::string name)
330 , shared_memory(nullptr)
332 if (!std::is_standard_layout<Goal>::value
333 || !std::is_standard_layout<Result>::value
334 || !std::is_standard_layout<Feedback>::value)
336 throw std::runtime_error(
"shm::ActionClient: Be setted not POD class!");
338 shared_memory =
new SharedMemoryPosix(shm_name, O_RDWR,
static_cast<PERM>(0));
341 template <
class Goal,
class Result,
class Feedback>
342 ActionClient<Goal, Result, Feedback>::~ActionClient()
344 if (shared_memory !=
nullptr)
346 delete shared_memory;
350 template <
class Goal,
class Result,
class Feedback>
352 ActionClient<Goal, Result, Feedback>::isServerConnected()
355 if (shared_memory->isDisconnected())
357 shared_memory->connect();
358 if (shared_memory->isDisconnected())
362 uint8_t *data_ptr = shared_memory->getPtr();
363 memory_ptr = data_ptr;
364 goal_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
365 data_ptr +=
sizeof(pthread_mutex_t);
366 goal_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
367 data_ptr +=
sizeof(pthread_cond_t);
368 goal_timestamp_us =
reinterpret_cast<uint64_t *
>(data_ptr);
369 data_ptr +=
sizeof(uint64_t);
370 goal_ptr =
reinterpret_cast<Goal *
>(data_ptr);
371 data_ptr +=
sizeof(Goal);
372 result_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
373 data_ptr +=
sizeof(pthread_mutex_t);
374 result_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
375 data_ptr +=
sizeof(pthread_cond_t);
376 result_timestamp_us =
reinterpret_cast<uint64_t *
>(data_ptr);
377 data_ptr +=
sizeof(uint64_t);
378 result_ptr =
reinterpret_cast<Result *
>(data_ptr);
379 data_ptr +=
sizeof(Result);
380 feedback_ptr =
reinterpret_cast<Feedback *
>(data_ptr);
381 data_ptr +=
sizeof(Feedback);
382 status_ptr =
reinterpret_cast<ACTION_STATUS *
>(data_ptr);
383 data_ptr +=
sizeof(ACTION_STATUS);
384 cancel_timestamp_us =
reinterpret_cast<uint64_t *
>(data_ptr);
390 template <
class Goal,
class Result,
class Feedback>
392 ActionClient<Goal, Result, Feedback>::sendGoal(Goal goal)
395 if (!(isServerConnected()))
400 current_result_timestamp_usec = *result_timestamp_us;
405 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
406 *goal_timestamp_us = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
407 pthread_cond_broadcast(goal_condition);
412 template <
class Goal,
class Result,
class Feedback>
414 ActionClient<Goal, Result, Feedback>::getResult()
419 template <
class Goal,
class Result,
class Feedback>
421 ActionClient<Goal, Result, Feedback>::getFeedback()
423 pthread_mutex_lock(result_mutex);
424 Feedback feedback_copy = *feedback_ptr;
425 pthread_mutex_unlock(result_mutex);
426 return feedback_copy;
429 template <
class Goal,
class Result,
class Feedback>
431 ActionClient<Goal, Result, Feedback>::getStatus()
436 template <
class Goal,
class Result,
class Feedback>
438 ActionClient<Goal, Result, Feedback>::cancelGoal()
441 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
442 *cancel_timestamp_us = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
445 template <
class Goal,
class Result,
class Feedback>
447 ActionClient<Goal, Result, Feedback>::waitForResult(
unsigned long wait_time_us)
450 long sec =
static_cast<long>(wait_time_us / 1000000);
451 long mod_sec =
static_cast<long>(wait_time_us % 1000000);
452 clock_gettime(CLOCK_REALTIME, &ts);
454 ts.tv_nsec+= mod_sec * 1000;
455 if (1000000000 <= ts.tv_nsec)
457 ts.tv_nsec -= 1000000000;
461 while (current_result_timestamp_usec >= *result_timestamp_us)
464 pthread_mutex_lock(result_mutex);
465 int ret = pthread_cond_timedwait(result_condition, result_mutex, &ts);
466 pthread_mutex_unlock(result_mutex);
467 if (ret == ETIMEDOUT)
475 template <
class Goal,
class Result,
class Feedback>
477 ActionClient<Goal, Result, Feedback>::waitForServer(uint64_t wait_time_us)
479 static const uint64_t SLEEP_PERIOD_us = 100000;
481 if (isServerConnected())
486 for (uint64_t time_index = 0; time_index < wait_time_us / SLEEP_PERIOD_us; time_index++)
488 if (isServerConnected())
492 usleep(SLEEP_PERIOD_us);
共有メモリからトピックを取得する購読者を表現するクラス
共有メモリで受信したリクエストからレスポンスを返すサーバーを表現するクラス
Class that abstracts the method of accessing shared memory.
Basic class definitions for accessing shared memory, ring buffers, etc. The notation is complianted R...