13 #ifndef __SHM_SERVICE_LIB_H__
14 #define __SHM_SERVICE_LIB_H__
34 template <
class Req,
class Res>
38 ServiceServer(std::string name, Res (*input_func)(Req request),
PERM perm = DEFAULT_PERM);
42 void initializeExclusiveAccess();
49 Res (*func)(Req request);
51 volatile bool shutdown_requested;
59 pthread_mutex_t *request_mutex;
60 pthread_cond_t *request_condition;
61 uint64_t *request_timestamp_usec;
63 pthread_mutex_t *response_mutex;
64 pthread_cond_t *response_condition;
65 uint64_t *response_timestamp_usec;
68 uint64_t current_request_timestamp_usec;
77 template <
class Req,
class Res>
84 bool call(Req request, Res *response);
85 bool call(Req request, Res *response,
unsigned long timeout_usec);
93 pthread_mutex_t *request_mutex;
94 pthread_cond_t *request_condition;
95 uint64_t *request_timestamp_usec;
97 pthread_mutex_t *response_mutex;
98 pthread_cond_t *response_condition;
99 uint64_t *response_timestamp_usec;
102 uint64_t current_response_timestamp_usec;
109 template <
class Req,
class Res>
112 , shutdown_requested(false)
115 , shared_memory(nullptr)
116 , memory_ptr(nullptr)
118 if (!std::is_standard_layout<Req>::value || !std::is_standard_layout<Res>::value)
120 throw std::runtime_error(
"shm::ServiceServer: Be setted not POD class!");
123 shared_memory =
new SharedMemoryPosix(shm_name, O_RDWR|O_CREAT, shm_perm);
124 shared_memory->connect( (
sizeof(pthread_mutex_t)+
sizeof(pthread_cond_t)+
sizeof(uint64_t)) * 2 +
sizeof(Req) +
sizeof(Res));
125 if (shared_memory->isDisconnected())
127 throw std::runtime_error(
"shm::Publisher: Cannot get memory!");
130 uint8_t *data_ptr = shared_memory->getPtr();
131 memory_ptr = data_ptr;
132 request_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
133 data_ptr +=
sizeof(pthread_mutex_t);
134 request_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
135 data_ptr +=
sizeof(pthread_cond_t);
136 request_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
137 data_ptr +=
sizeof(uint64_t);
138 request_ptr =
reinterpret_cast<Req *
>(data_ptr);
139 data_ptr +=
sizeof(Req);
140 response_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
141 data_ptr +=
sizeof(pthread_mutex_t);
142 response_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
143 data_ptr +=
sizeof(pthread_cond_t);
144 response_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
145 data_ptr +=
sizeof(uint64_t);
146 response_ptr =
reinterpret_cast<Res *
>(data_ptr);
148 initializeExclusiveAccess();
151 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
152 *request_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
153 *response_timestamp_usec = *request_timestamp_usec;
154 current_request_timestamp_usec = *request_timestamp_usec;
156 pthread_create(&thread, NULL,
reinterpret_cast<void* (*)(
void*)
>(&ServiceServer<Req, Res>::called_loop),
this);
159 template <
class Req,
class Res>
160 ServiceServer<Req, Res>::~ServiceServer()
163 shutdown_requested =
true;
166 pthread_cond_broadcast(request_condition);
169 pthread_cancel(thread);
170 pthread_join(thread,
nullptr);
172 shared_memory->disconnect();
173 if (shared_memory !=
nullptr)
175 delete shared_memory;
179 template <
class Req,
class Res>
181 ServiceServer<Req, Res>::initializeExclusiveAccess()
183 pthread_condattr_t request_cond_attr;
184 pthread_condattr_init(&request_cond_attr);
185 pthread_condattr_setpshared(&request_cond_attr, PTHREAD_PROCESS_SHARED);
186 pthread_cond_init(request_condition, &request_cond_attr);
187 pthread_condattr_destroy(&request_cond_attr);
189 pthread_mutexattr_t request_m_attr;
190 pthread_mutexattr_init(&request_m_attr);
191 pthread_mutexattr_setpshared(&request_m_attr, PTHREAD_PROCESS_SHARED);
192 pthread_mutex_init(request_mutex, &request_m_attr);
193 pthread_mutexattr_destroy(&request_m_attr);
195 pthread_condattr_t response_cond_attr;
196 pthread_condattr_init(&response_cond_attr);
197 pthread_condattr_setpshared(&response_cond_attr, PTHREAD_PROCESS_SHARED);
198 pthread_cond_init(response_condition, &response_cond_attr);
199 pthread_condattr_destroy(&response_cond_attr);
201 pthread_mutexattr_t response_m_attr;
202 pthread_mutexattr_init(&response_m_attr);
203 pthread_mutexattr_setpshared(&response_m_attr, PTHREAD_PROCESS_SHARED);
204 pthread_mutex_init(response_mutex, &response_m_attr);
205 pthread_mutexattr_destroy(&response_m_attr);
208 template <
class Req,
class Res>
210 ServiceServer<Req, Res>::loop()
213 std::unique_ptr<Req> current_request_ptr = std::make_unique<Req>();
214 std::unique_ptr<Res> result_ptr = std::make_unique<Res>();
216 while (!shutdown_requested)
219 pthread_mutex_lock(request_mutex);
220 while (current_request_timestamp_usec >= *request_timestamp_usec && !shutdown_requested)
223 pthread_cond_wait(request_condition, request_mutex);
227 if (shutdown_requested)
229 pthread_mutex_unlock(request_mutex);
234 current_request_timestamp_usec = *request_timestamp_usec;
235 *current_request_ptr = *request_ptr;
236 pthread_mutex_unlock(request_mutex);
239 *result_ptr = func(*current_request_ptr);
242 if (shutdown_requested)
248 pthread_mutex_lock(response_mutex);
249 *response_ptr = *result_ptr;
251 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
252 *response_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
253 pthread_mutex_unlock(response_mutex);
255 pthread_cond_broadcast(response_condition);
260 template <
class Req,
class Res>
261 ServiceClient<Req, Res>::ServiceClient(std::string name)
263 , shared_memory(nullptr)
265 if (!std::is_standard_layout<Req>::value || !std::is_standard_layout<Res>::value)
267 throw std::runtime_error(
"shm::ServiceClient: Be setted not POD class!");
269 shared_memory =
new SharedMemoryPosix(shm_name, O_RDWR,
static_cast<PERM>(0));
272 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
273 current_response_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
276 template <
class Req,
class Res>
277 ServiceClient<Req, Res>::~ServiceClient()
279 if (shared_memory !=
nullptr)
281 delete shared_memory;
285 template <
class Req,
class Res>
287 ServiceClient<Req, Res>::call(Req request, Res *response)
290 return call(request, response, 5000000);
293 template <
class Req,
class Res>
295 ServiceClient<Req, Res>::call(Req request, Res *response,
unsigned long timeout_usec)
298 if (shared_memory->isDisconnected())
300 shared_memory->connect();
301 if (shared_memory->isDisconnected())
305 uint8_t *data_ptr = shared_memory->getPtr();
306 memory_ptr = data_ptr;
307 request_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
308 data_ptr +=
sizeof(pthread_mutex_t);
309 request_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
310 data_ptr +=
sizeof(pthread_cond_t);
311 request_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
312 data_ptr +=
sizeof(uint64_t);
313 request_ptr =
reinterpret_cast<Req *
>(data_ptr);
314 data_ptr +=
sizeof(Req);
315 response_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
316 data_ptr +=
sizeof(pthread_mutex_t);
317 response_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
318 data_ptr +=
sizeof(pthread_cond_t);
319 response_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
320 data_ptr +=
sizeof(uint64_t);
321 response_ptr =
reinterpret_cast<Res *
>(data_ptr);
325 *request_ptr = request;
327 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
328 *request_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
330 pthread_cond_broadcast(request_condition);
333 uint64_t start_time = *request_timestamp_usec;
334 uint64_t end_time = start_time + timeout_usec;
336 while (current_response_timestamp_usec >= *response_timestamp_usec)
339 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
340 uint64_t current_time = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
341 if (current_time > end_time)
347 pthread_mutex_lock(response_mutex);
348 struct timespec wait_time;
349 wait_time.tv_sec = 0;
350 wait_time.tv_nsec = 10000000;
351 pthread_cond_timedwait(response_condition, response_mutex, &wait_time);
352 pthread_mutex_unlock(response_mutex);
354 current_response_timestamp_usec = *response_timestamp_usec;
357 *response = *response_ptr;
共有メモリからトピックを取得する購読者を表現するクラス
共有メモリで受信したリクエストからレスポンスを返すサーバーを表現するクラス
Class that abstracts the method of accessing shared memory.
Basic class definitions for accessing shared memory, ring buffers, etc. The notation is complianted R...