13 #ifndef __SHM_SERVICE_LIB_H__
14 #define __SHM_SERVICE_LIB_H__
33 template <
class Req,
class Res>
37 ServiceServer(std::string name, Res (*input_func)(Req request),
PERM perm = DEFAULT_PERM);
41 void initializeExclusiveAccess();
48 Res (*func)(Req request);
57 pthread_mutex_t *request_mutex;
58 pthread_cond_t *request_condition;
59 uint64_t *request_timestamp_usec;
61 pthread_mutex_t *response_mutex;
62 pthread_cond_t *response_condition;
63 uint64_t *response_timestamp_usec;
66 uint64_t current_request_timestamp_usec;
75 template <
class Req,
class Res>
82 bool call(Req request, Res *response);
90 pthread_mutex_t *request_mutex;
91 pthread_cond_t *request_condition;
92 uint64_t *request_timestamp_usec;
94 pthread_mutex_t *response_mutex;
95 pthread_cond_t *response_condition;
96 uint64_t *response_timestamp_usec;
99 uint64_t current_response_timestamp_usec;
106 template <
class Req,
class Res>
111 , shared_memory(nullptr)
112 , memory_ptr(nullptr)
114 if (!std::is_standard_layout<Req>::value || !std::is_standard_layout<Res>::value)
116 throw std::runtime_error(
"shm::ServiceServer: Be setted not POD class!");
119 shared_memory =
new SharedMemoryPosix(shm_name, O_RDWR|O_CREAT, shm_perm);
120 shared_memory->connect( (
sizeof(pthread_mutex_t)+
sizeof(pthread_cond_t)+
sizeof(uint64_t)) * 2 +
sizeof(Req) +
sizeof(Res));
121 if (shared_memory->isDisconnected())
123 throw std::runtime_error(
"shm::Publisher: Cannot get memory!");
126 uint8_t *data_ptr = shared_memory->getPtr();
127 memory_ptr = data_ptr;
128 request_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
129 data_ptr +=
sizeof(pthread_mutex_t);
130 request_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
131 data_ptr +=
sizeof(pthread_cond_t);
132 request_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
133 data_ptr +=
sizeof(uint64_t);
134 request_ptr =
reinterpret_cast<Req *
>(data_ptr);
135 data_ptr +=
sizeof(Req);
136 response_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
137 data_ptr +=
sizeof(pthread_mutex_t);
138 response_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
139 data_ptr +=
sizeof(pthread_cond_t);
140 response_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
141 data_ptr +=
sizeof(uint64_t);
142 response_ptr =
reinterpret_cast<Res *
>(data_ptr);
144 initializeExclusiveAccess();
147 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
148 *request_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
149 *response_timestamp_usec = *request_timestamp_usec;
150 current_request_timestamp_usec = *request_timestamp_usec;
152 pthread_create(&thread, NULL,
reinterpret_cast<void* (*)(
void*)
>(&ServiceServer<Req, Res>::called_loop),
this);
155 template <
class Req,
class Res>
156 ServiceServer<Req, Res>::~ServiceServer()
158 pthread_cancel(thread);
160 shared_memory->disconnect();
161 if (shared_memory !=
nullptr)
163 delete shared_memory;
167 template <
class Req,
class Res>
169 ServiceServer<Req, Res>::initializeExclusiveAccess()
171 pthread_condattr_t request_cond_attr;
172 pthread_condattr_init(&request_cond_attr);
173 pthread_condattr_setpshared(&request_cond_attr, PTHREAD_PROCESS_SHARED);
174 pthread_cond_init(request_condition, &request_cond_attr);
175 pthread_condattr_destroy(&request_cond_attr);
177 pthread_mutexattr_t request_m_attr;
178 pthread_mutexattr_init(&request_m_attr);
179 pthread_mutexattr_setpshared(&request_m_attr, PTHREAD_PROCESS_SHARED);
180 pthread_mutex_init(request_mutex, &request_m_attr);
181 pthread_mutexattr_destroy(&request_m_attr);
183 pthread_condattr_t response_cond_attr;
184 pthread_condattr_init(&response_cond_attr);
185 pthread_condattr_setpshared(&response_cond_attr, PTHREAD_PROCESS_SHARED);
186 pthread_cond_init(response_condition, &response_cond_attr);
187 pthread_condattr_destroy(&response_cond_attr);
189 pthread_mutexattr_t response_m_attr;
190 pthread_mutexattr_init(&response_m_attr);
191 pthread_mutexattr_setpshared(&response_m_attr, PTHREAD_PROCESS_SHARED);
192 pthread_mutex_init(response_mutex, &response_m_attr);
193 pthread_mutexattr_destroy(&response_m_attr);
196 template <
class Req,
class Res>
198 ServiceServer<Req, Res>::loop()
202 while (current_request_timestamp_usec >= *request_timestamp_usec)
205 pthread_mutex_lock(request_mutex);
206 pthread_cond_wait(request_condition, request_mutex);
207 pthread_mutex_unlock(request_mutex);
209 current_request_timestamp_usec = *request_timestamp_usec;
211 *response_ptr = func(*request_ptr);
213 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
214 *response_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
216 pthread_cond_broadcast(response_condition);
221 template <
class Req,
class Res>
222 ServiceClient<Req, Res>::ServiceClient(std::string name)
224 , shared_memory(nullptr)
226 if (!std::is_standard_layout<Req>::value || !std::is_standard_layout<Res>::value)
228 throw std::runtime_error(
"shm::ServiceClient: Be setted not POD class!");
230 shared_memory =
new SharedMemoryPosix(shm_name, O_RDWR,
static_cast<PERM>(0));
233 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
234 current_response_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
237 template <
class Req,
class Res>
238 ServiceClient<Req, Res>::~ServiceClient()
240 if (shared_memory !=
nullptr)
242 delete shared_memory;
246 template <
class Req,
class Res>
248 ServiceClient<Req, Res>::call(Req request, Res *response)
251 if (shared_memory->isDisconnected())
253 shared_memory->connect();
254 if (shared_memory->isDisconnected())
258 uint8_t *data_ptr = shared_memory->getPtr();
259 memory_ptr = data_ptr;
260 request_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
261 data_ptr +=
sizeof(pthread_mutex_t);
262 request_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
263 data_ptr +=
sizeof(pthread_cond_t);
264 request_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
265 data_ptr +=
sizeof(uint64_t);
266 request_ptr =
reinterpret_cast<Req *
>(data_ptr);
267 data_ptr +=
sizeof(Req);
268 response_mutex =
reinterpret_cast<pthread_mutex_t *
>(data_ptr);
269 data_ptr +=
sizeof(pthread_mutex_t);
270 response_condition =
reinterpret_cast<pthread_cond_t *
>(data_ptr);
271 data_ptr +=
sizeof(pthread_cond_t);
272 response_timestamp_usec =
reinterpret_cast<uint64_t *
>(data_ptr);
273 data_ptr +=
sizeof(uint64_t);
274 response_ptr =
reinterpret_cast<Res *
>(data_ptr);
278 *request_ptr = request;
280 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
281 *request_timestamp_usec = ((uint64_t) ts.tv_sec * 1000000L) + ((uint64_t) ts.tv_nsec / 1000L);
283 pthread_cond_broadcast(request_condition);
285 while (current_response_timestamp_usec >= *response_timestamp_usec)
288 pthread_mutex_lock(response_mutex);
289 pthread_cond_wait(response_condition, response_mutex);
290 pthread_mutex_unlock(response_mutex);
292 current_response_timestamp_usec = *response_timestamp_usec;
295 *response = *response_ptr;
304 #endif //__SHM_SERVICE_LIB_H__