Go to the documentation of this file.
11 #ifndef MERCURY_MACROS_H
12 #define MERCURY_MACROS_H
19 #include <boost/preprocessor.hpp>
22 #define MERCURY_GEN_FALSE 0
23 #define MERCURY_GEN_TRUE 1
28 #define HG_GEN_RET_PARAM(ret_type) ((ret_type)(ret))
31 #define HG_GEN_GET_TYPE(field) BOOST_PP_SEQ_HEAD(field)
32 #define HG_GEN_GET_NAME(field) BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_TAIL(field))
35 #define HG_GEN_STRUCT_FIELD(r, data, param) \
36 HG_GEN_GET_TYPE(param) HG_GEN_GET_NAME(param);
39 #define HG_GEN_STRUCT(struct_type_name, fields) \
42 BOOST_PP_SEQ_FOR_EACH(HG_GEN_STRUCT_FIELD, , fields) \
47 #define HG_GEN_PROC(r, struct_name, field) \
48 ret = BOOST_PP_CAT(hg_proc_, HG_GEN_GET_TYPE(field) \
49 (proc, &struct_name->HG_GEN_GET_NAME(field))); \
50 if (ret != HG_SUCCESS) { \
51 HG_ERROR_DEFAULT("Proc error"); \
57 #define HG_GEN_STRUCT_PROC(struct_type_name, fields) \
58 static HG_INLINE hg_return_t \
59 BOOST_PP_CAT(hg_proc_, struct_type_name) \
60 (hg_proc_t proc, void *data) \
62 hg_return_t ret = HG_SUCCESS; \
63 struct_type_name *struct_data = (struct_type_name *) data; \
65 BOOST_PP_SEQ_FOR_EACH(HG_GEN_PROC, struct_data, fields) \
71 #define HG_GEN_PARAM_NAME(r, prefix, i, param) ((param) (BOOST_PP_CAT(prefix, i)))
74 #define HG_GEN_PARAM_NAME_SEQ(prefix, type_seq) \
75 BOOST_PP_SEQ_FOR_EACH_I(HG_GEN_PARAM_NAME, prefix, type_seq)
78 #define HG_GEN_DECL_FUNC_PARAM(r, is_ref, param) \
79 (HG_GEN_GET_TYPE(param) \
80 BOOST_PP_IF(is_ref, *, BOOST_PP_EMPTY())HG_GEN_GET_NAME(param))
83 #define HG_GEN_DECL_FUNC_PARAM_SEQ(is_ref, param_seq) \
84 BOOST_PP_SEQ_FOR_EACH(HG_GEN_DECL_FUNC_PARAM, is_ref, param_seq)
87 #define HG_GEN_DECL_FUNC_PARAMS(with_input, in_params, extra_in_params, \
88 with_output, out_params, extra_out_params) \
89 BOOST_PP_SEQ_TO_TUPLE( \
90 BOOST_PP_IF(BOOST_PP_OR(with_input, with_output), \
91 HG_GEN_DECL_FUNC_PARAM_SEQ(MERCURY_GEN_FALSE, in_params) \
92 HG_GEN_DECL_FUNC_PARAM_SEQ(MERCURY_GEN_FALSE, extra_in_params) \
93 HG_GEN_DECL_FUNC_PARAM_SEQ(MERCURY_GEN_TRUE, out_params) \
94 HG_GEN_DECL_FUNC_PARAM_SEQ(MERCURY_GEN_TRUE, extra_out_params), \
100 #define HG_GEN_FUNC_PARAM(r, is_ref, param) \
101 (BOOST_PP_IF(is_ref, &, BOOST_PP_EMPTY())HG_GEN_GET_NAME(param))
104 #define HG_GEN_FUNC_PARAM_SEQ(is_ref, param_seq) \
105 BOOST_PP_SEQ_FOR_EACH(HG_GEN_FUNC_PARAM, is_ref, param_seq)
108 #define HG_GEN_FUNC_PARAMS(with_input, in_params, extra_in_params, \
109 with_output, out_params, extra_out_params) \
110 BOOST_PP_SEQ_TO_TUPLE( \
111 BOOST_PP_IF(BOOST_PP_OR(with_input, with_output), \
112 HG_GEN_FUNC_PARAM_SEQ(MERCURY_GEN_FALSE, in_params) \
113 HG_GEN_FUNC_PARAM_SEQ(MERCURY_GEN_FALSE, extra_in_params) \
114 HG_GEN_FUNC_PARAM_SEQ(MERCURY_GEN_TRUE, out_params) \
115 HG_GEN_FUNC_PARAM_SEQ(MERCURY_GEN_TRUE, extra_out_params), \
121 #define HG_GEN_DECL_PARAMS(param_seq) \
122 BOOST_PP_SEQ_FOR_EACH(HG_GEN_STRUCT_FIELD, , param_seq)
125 #define HG_SET_STRUCT_PARAM(r, struct_name, param) \
126 struct_name.HG_GEN_GET_NAME(param) = HG_GEN_GET_NAME(param);
129 #define HG_SET_STRUCT_PARAMS(struct_name, params) \
130 BOOST_PP_SEQ_FOR_EACH(HG_SET_STRUCT_PARAM, struct_name, params)
133 #define HG_GET_STRUCT_PARAM(r, struct_name, param) \
134 HG_GEN_GET_NAME(param) = struct_name.HG_GEN_GET_NAME(param);
137 #define HG_GET_STRUCT_PARAMS(struct_name, params) \
138 BOOST_PP_SEQ_FOR_EACH(HG_GET_STRUCT_PARAM, struct_name, params)
141 #define HG_GET_OUT_STRUCT_PARAM(r, struct_name, param) \
142 *HG_GEN_GET_NAME(param) = struct_name.HG_GEN_GET_NAME(param);
145 #define HG_GET_OUT_STRUCT_PARAMS(struct_name, params) \
146 BOOST_PP_SEQ_FOR_EACH(HG_GET_OUT_STRUCT_PARAM, struct_name, params)
151 #define HG_BULK_INIT_PARAM ((hg_bool_t)(bulk_initialized))
154 #define HG_BULK_CONST_BUF ((const void*)(bulk_buf))
155 #define HG_BULK_BUF ((void*)(bulk_buf))
156 #define HG_BULK_COUNT ((hg_uint64_t)(bulk_count))
158 #define HG_BULK_EXTRA_IN_PARAM \
159 HG_BULK_BUF HG_BULK_COUNT
162 #define HG_BULK_PARAM ((hg_bulk_t)(bulk_handle))
165 #define HG_BULK_BLOCK_PARAM ((hg_bulk_t)(bulk_block_handle))
168 #define HG_BULK_REQUEST_PARAM ((hg_bulk_request_t)(bulk_request))
171 #define HG_BULK_ADDR_PARAM ((na_addr_t)(bulk_addr))
174 #define HG_BULK_INITIALIZE(with_ret, fail_ret) \
175 HG_Bulk_initialized(&HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_INIT_PARAM)), \
177 if (!HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_INIT_PARAM))) { \
178 hg_ret = HG_Bulk_init(na_class); \
179 if (hg_ret != HG_SUCCESS) { \
180 HG_ERROR_DEFAULT("Could not initialize bulk data shipper"); \
181 BOOST_PP_IF(with_ret, ret = fail_ret;, BOOST_PP_EMPTY()) \
187 #define HG_BULK_REGISTER(with_ret, fail_ret, bulk_read) \
188 hg_ret = HG_Bulk_handle_create( \
189 1, &HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(0, HG_BULK_EXTRA_IN_PARAM)),\
190 &HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(1, HG_BULK_EXTRA_IN_PARAM)), \
191 BOOST_PP_IF(bulk_read, HG_BULK_READ_ONLY, HG_BULK_READWRITE), \
193 if (hg_ret != HG_SUCCESS) { \
194 HG_ERROR_DEFAULT("Could not create bulk data handle\n"); \
195 BOOST_PP_IF(with_ret, ret = fail_ret;, BOOST_PP_EMPTY()) \
200 #define HG_BULK_FREE(with_ret, fail_ret) \
201 hg_ret = HG_Bulk_handle_free( \
202 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_PARAM))); \
203 if (hg_ret != HG_SUCCESS) { \
204 HG_ERROR_DEFAULT("Could not free bulk data handle"); \
205 BOOST_PP_IF(with_ret, ret = fail_ret;, BOOST_PP_EMPTY()) \
210 #define HG_GEN_DECL_BULK_PARAMS \
211 HG_GEN_DECL_PARAMS(HG_BULK_PARAM HG_BULK_BLOCK_PARAM \
212 HG_BULK_REQUEST_PARAM HG_BULK_EXTRA_IN_PARAM HG_BULK_ADDR_PARAM)
215 #define HG_BULK_GET_ADDR \
216 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_ADDR_PARAM)) = \
217 HG_Handler_get_addr(handle);
220 #define HG_BULK_BLOCK_ALLOCATE \
221 HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(1, HG_BULK_EXTRA_IN_PARAM)) = \
222 HG_Bulk_handle_get_size(HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_PARAM))); \
223 HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(0, HG_BULK_EXTRA_IN_PARAM)) = \
224 malloc(HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(1, HG_BULK_EXTRA_IN_PARAM))); \
225 HG_Bulk_handle_create(1, &HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(0, HG_BULK_EXTRA_IN_PARAM)), \
226 &HG_GEN_GET_NAME(BOOST_PP_SEQ_ELEM(1, HG_BULK_EXTRA_IN_PARAM)), \
228 &HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_BLOCK_PARAM)));
231 #define HG_BULK_BLOCK_FREE \
232 hg_ret = HG_Bulk_handle_free( \
233 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_BLOCK_PARAM))); \
234 if (hg_ret != HG_SUCCESS) { \
235 HG_ERROR_DEFAULT("Could not free block call"); \
241 #define HG_BULK_TRANSFER(bulk_read) \
242 hg_ret = HG_Bulk_transfer(BOOST_PP_IF(bulk_read, HG_BULK_PULL, HG_BULK_PUSH), \
243 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_ADDR_PARAM)), \
244 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_PARAM)), \
246 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_BLOCK_PARAM)), \
248 HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_COUNT)), \
249 &HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_REQUEST_PARAM))); \
250 if (hg_ret != HG_SUCCESS) { \
251 HG_ERROR_DEFAULT("Could not transfer bulk data"); \
254 hg_ret = HG_Bulk_wait(HG_GEN_GET_NAME(BOOST_PP_SEQ_HEAD(HG_BULK_REQUEST_PARAM)), \
255 HG_MAX_IDLE_TIME, HG_STATUS_IGNORE); \
256 if (hg_ret != HG_SUCCESS) { \
257 HG_ERROR_DEFAULT("Could not complete bulk data transfer"); \
268 #define MERCURY_GEN_PROC(struct_type_name, fields) \
269 HG_GEN_STRUCT(struct_type_name, fields) \
270 HG_GEN_STRUCT_PROC(struct_type_name, fields)
281 #define MERCURY_GEN_STRUCT_PROC(struct_type_name, fields) \
282 HG_GEN_STRUCT_PROC(struct_type_name, fields)
285 #define MERCURY_REGISTER(func_name, in_struct_type_name, out_struct_type_name, \
287 HG_Register(func_name, BOOST_PP_CAT(hg_proc_, in_struct_type_name), \
288 BOOST_PP_CAT(hg_proc_, out_struct_type_name), rpc_cb)
297 #ifndef MERCURY_HANDLER_GEN_LOG_MESSAGE
298 #define MERCURY_HANDLER_GEN_LOG_MESSAGE(x)
302 #define MERCURY_GEN_RPC_STUB(gen_func_name, func_name, \
303 with_ret, ret_type_name, ret_fail, \
304 with_input, in_struct_type_name, in_params, \
305 with_output, out_struct_type_name, out_params, \
306 with_bulk, bulk_read) \
307 BOOST_PP_IF(with_ret, ret_type_name, void) \
308 gen_func_name HG_GEN_DECL_FUNC_PARAMS(with_input, in_params, \
309 BOOST_PP_IF(with_bulk, HG_BULK_EXTRA_IN_PARAM, BOOST_PP_EMPTY()), \
310 with_output, out_params, ) \
312 BOOST_PP_IF(with_input, \
313 in_struct_type_name in_struct;, BOOST_PP_EMPTY()) \
314 BOOST_PP_IF(BOOST_PP_OR(with_output, with_ret), \
315 out_struct_type_name out_struct;, BOOST_PP_EMPTY()) \
316 BOOST_PP_IF(with_ret, ret_type_name ret;, BOOST_PP_EMPTY()) \
317 na_class_t *na_class; \
319 const char *info_string; \
322 BOOST_PP_IF(with_bulk, HG_GEN_DECL_PARAMS(HG_BULK_PARAM), BOOST_PP_EMPTY()) \
323 hg_request_t request; \
324 hg_status_t status; \
325 hg_bool_t hg_initialized; \
326 hg_bool_t func_registered; \
327 hg_return_t hg_ret; \
328 na_return_t na_ret; \
331 HG_Initialized(&hg_initialized, &na_class); \
332 if (!hg_initialized) { \
333 info_string = getenv(HG_PORT_NAME); \
334 if (!info_string) { \
335 HG_ERROR_DEFAULT(HG_PORT_NAME " env var not set"); \
336 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
339 na_class = NA_Initialize(info_string, 0); \
340 hg_ret = HG_Init(na_class); \
341 if (hg_ret != HG_SUCCESS) { \
342 HG_ERROR_DEFAULT("Could not initialize Mercury"); \
343 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
349 server_name = getenv(HG_PORT_NAME); \
351 na_ret = NA_Addr_lookup_wait(na_class, server_name, &addr); \
352 if (na_ret != NA_SUCCESS) { \
353 HG_ERROR_DEFAULT("Could not lookup addr"); \
354 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
359 HG_Registered(BOOST_PP_STRINGIZE(func_name), &func_registered, &id); \
360 if (!func_registered) { \
361 id = MERCURY_REGISTER(BOOST_PP_STRINGIZE(func_name), \
362 BOOST_PP_IF(with_input, in_struct_type_name, void), \
364 BOOST_PP_OR(with_output, with_ret), \
365 out_struct_type_name, \
372 BOOST_PP_IF(with_bulk, HG_BULK_REGISTER(with_ret, ret_fail, bulk_read), \
376 BOOST_PP_IF(with_input, \
377 HG_SET_STRUCT_PARAMS(in_struct, in_params \
378 BOOST_PP_IF(with_bulk, HG_BULK_PARAM, BOOST_PP_EMPTY())), \
382 hg_ret = HG_Forward(addr, id, \
383 BOOST_PP_IF(with_input, &in_struct, NULL), \
384 BOOST_PP_IF(BOOST_PP_OR(with_output, with_ret), &out_struct, NULL), \
386 if (hg_ret != HG_SUCCESS) { \
387 HG_ERROR_DEFAULT("Could not forward call"); \
388 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
395 hg_ret = HG_Wait(request, HG_MAX_IDLE_TIME, &status); \
396 if (hg_ret != HG_SUCCESS) { \
397 HG_ERROR_DEFAULT("Error during wait"); \
398 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
402 HG_ERROR_DEFAULT("Operation did not complete"); \
403 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
407 BOOST_PP_IF(with_bulk, HG_BULK_FREE(with_ret, ret_fail), BOOST_PP_EMPTY()) \
410 BOOST_PP_IF(with_ret, \
411 HG_GET_STRUCT_PARAMS(out_struct, ((ret_type)(ret))), \
413 BOOST_PP_IF(with_output, \
414 HG_GET_OUT_STRUCT_PARAMS(out_struct, out_params), \
418 hg_ret = HG_Request_free(request); \
419 if (hg_ret != HG_SUCCESS) { \
420 HG_ERROR_DEFAULT("Could not free request"); \
421 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
426 na_ret = NA_Addr_free(na_class, addr); \
427 if (na_ret != NA_SUCCESS) { \
428 HG_ERROR_DEFAULT("Could not free addr"); \
429 BOOST_PP_IF(with_ret, ret = ret_fail;, BOOST_PP_EMPTY()) \
435 return BOOST_PP_IF(with_ret, ret, BOOST_PP_EMPTY()); \
439 #define MERCURY_HANDLER_GEN_CALLBACK_STUB(gen_func_name, func_name, \
440 with_ret, ret_type, \
441 with_input, in_struct_type_name, in_params, \
442 with_output, out_struct_type_name, out_params, \
443 with_bulk, bulk_read, \
444 with_thread, thread_pool) \
446 BOOST_PP_IF(with_thread, \
447 HG_THREAD_RETURN_TYPE BOOST_PP_CAT(gen_func_name, _thread), \
448 hg_return_t gen_func_name) \
450 BOOST_PP_IF(with_thread, void *arg, hg_handle_t handle) \
453 BOOST_PP_IF(with_thread, \
454 hg_handle_t handle = (hg_handle_t) arg; \
455 hg_thread_ret_t thread_ret = (hg_thread_ret_t) 0; \
458 hg_return_t hg_ret = HG_SUCCESS; \
459 BOOST_PP_IF(with_input, \
460 in_struct_type_name in_struct;, BOOST_PP_EMPTY()) \
461 BOOST_PP_IF(BOOST_PP_OR(with_output, with_ret), \
462 out_struct_type_name out_struct;, BOOST_PP_EMPTY()) \
463 BOOST_PP_IF(with_input, HG_GEN_DECL_PARAMS(in_params), BOOST_PP_EMPTY()) \
464 BOOST_PP_IF(with_output, HG_GEN_DECL_PARAMS(out_params), BOOST_PP_EMPTY()) \
465 BOOST_PP_IF(with_ret, ret_type ret;, BOOST_PP_EMPTY()) \
466 BOOST_PP_IF(with_bulk, HG_GEN_DECL_BULK_PARAMS, BOOST_PP_EMPTY()) \
468 BOOST_PP_IF(with_bulk, HG_BULK_GET_ADDR, BOOST_PP_EMPTY()) \
471 BOOST_PP_IF(with_input, \
472 hg_ret = HG_Handler_get_input(handle, &in_struct); \
473 if (hg_ret != HG_SUCCESS) { \
474 HG_ERROR_DEFAULT("Could not get input struct"); \
479 HG_GET_STRUCT_PARAMS(in_struct, in_params \
480 BOOST_PP_IF(with_bulk, HG_BULK_PARAM, BOOST_PP_EMPTY())) \
481 , BOOST_PP_EMPTY()) \
483 BOOST_PP_IF(with_bulk, HG_BULK_BLOCK_ALLOCATE, BOOST_PP_EMPTY()) \
484 BOOST_PP_IF(with_bulk, \
485 BOOST_PP_IF(bulk_read, \
486 HG_BULK_TRANSFER(bulk_read), BOOST_PP_EMPTY()), \
490 MERCURY_HANDLER_GEN_LOG_MESSAGE(BOOST_PP_STRINGIZE(func_name)); \
491 BOOST_PP_IF(with_ret, ret =, BOOST_PP_EMPTY()) \
492 func_name HG_GEN_FUNC_PARAMS(with_input, in_params, \
493 BOOST_PP_IF(with_bulk, HG_BULK_EXTRA_IN_PARAM, BOOST_PP_EMPTY()), \
494 with_output, out_params, ); \
496 BOOST_PP_IF(with_bulk, \
497 BOOST_PP_IF(bulk_read, \
498 BOOST_PP_EMPTY(), HG_BULK_TRANSFER(bulk_read)), \
501 BOOST_PP_IF(with_bulk, HG_BULK_BLOCK_FREE, BOOST_PP_EMPTY()) \
504 BOOST_PP_IF(with_ret, \
505 HG_SET_STRUCT_PARAMS(out_struct, ((ret_type)(ret))), \
507 BOOST_PP_IF(with_output, \
508 HG_SET_STRUCT_PARAMS(out_struct, out_params), \
512 hg_ret = HG_Handler_start_output(handle, \
513 BOOST_PP_IF(BOOST_PP_OR(with_output, with_ret), \
516 if (hg_ret != HG_SUCCESS) { \
517 HG_ERROR_DEFAULT("Could not start output"); \
521 BOOST_PP_IF(with_input, \
522 hg_ret = HG_Handler_free_input(handle, &in_struct); \
523 if (hg_ret != HG_SUCCESS) { \
524 HG_ERROR_DEFAULT("Could not free input struct"); \
527 , BOOST_PP_EMPTY()) \
529 hg_ret = HG_Handler_free(handle); \
530 if (hg_ret != HG_SUCCESS) { \
531 HG_ERROR_DEFAULT("Could not free handle"); \
537 BOOST_PP_IF(with_thread, \
542 BOOST_PP_IF(with_thread, \
544 gen_func_name(hg_handle_t handle) \
546 hg_return_t ret = HG_SUCCESS; \
547 hg_thread_pool_post(thread_pool, \
548 &BOOST_PP_CAT(gen_func_name, _thread), handle); \
555 #define MERCURY_REGISTER(func_name, in_struct_type_name, out_struct_type_name, \
557 HG_Register(func_name, hg_proc_ ## in_struct_type_name, \
558 hg_proc_ ## out_struct_type_name, rpc_cb)
565 #define hg_proc_void NULL