margo.h 21 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * (C) 2015 The University of Chicago
 * 
 * See COPYRIGHT in top-level directory.
 */

#ifndef __MARGO
#define __MARGO

10 11 12 13
#ifdef __cplusplus
extern "C" {
#endif

14 15 16 17 18 19
/* This is to prevent the user from usin HG_Register_data
 * and HG_Registered_data, which are replaced with
 * margo_register_data and margo_registered_data
 * respecively.
 */

20 21 22 23 24
#include <mercury_bulk.h>
#include <mercury.h>
#include <mercury_macros.h>
#include <abt.h>

25 26
#undef MERCURY_REGISTER

27 28
struct margo_instance;
typedef struct margo_instance* margo_instance_id;
29
typedef struct margo_data* margo_data_ptr;
30

31
#define MARGO_INSTANCE_NULL ((margo_instance_id)NULL)
32
#define MARGO_DEFAULT_MPLEX_ID 0
33
#define MARGO_RPC_ID_IGNORE ((hg_id_t*)NULL)
Jonathan Jenkins's avatar
Jonathan Jenkins committed
34 35 36

/**
 * Initializes margo library.
Shane Snyder's avatar
Shane Snyder committed
37 38
 * @param [in] addr_str            Mercury host address with port number
 * @param [in] listen_flag         Boolean flag to listen for incoming connections
Jonathan Jenkins's avatar
Jonathan Jenkins committed
39 40
 * @param [in] use_progress_thread Boolean flag to use a dedicated thread for
 *                                 running Mercury's progress loop. If false,
41
 *                                 it will run in the caller's thread context.
Jonathan Jenkins's avatar
Jonathan Jenkins committed
42 43
 * @param [in] rpc_thread_count    Number of threads to use for running RPC
 *                                 calls. A value of 0 directs Margo to execute
44 45 46 47 48 49
 *                                 RPCs in the caller's thread context.
 *                                 Clients (i.e processes that will *not* 
 *                                 service incoming RPCs) should use a value 
 *                                 of 0. A value of -1 directs Margo to use 
 *                                 the same execution context as that used 
 *                                 for Mercury progress.
Jonathan Jenkins's avatar
Jonathan Jenkins committed
50
 * @returns margo instance id on success, MARGO_INSTANCE_NULL upon error
51 52 53 54 55
 *
 * NOTE: Servers (processes expecting to service incoming RPC requests) must
 * specify non-zero values for use_progress_thread and rpc_thread_count *or*
 * call margo_wait_for_finalize() after margo_init() to relinguish control to 
 * Margo.
Jonathan Jenkins's avatar
Jonathan Jenkins committed
56
 */
Shane Snyder's avatar
Shane Snyder committed
57 58 59 60 61
margo_instance_id margo_init(
    const char *addr_str,
    int listen_flag,
    int use_progress_thread,
    int rpc_thread_count);
Jonathan Jenkins's avatar
Jonathan Jenkins committed
62

63
/**
Jonathan Jenkins's avatar
doc fix  
Jonathan Jenkins committed
64
 * Initializes margo library from given argobots and Mercury instances.
Philip Carns's avatar
Philip Carns committed
65 66 67
 * @param [in] progress_pool Argobots pool to drive communication
 * @param [in] handler_pool Argobots pool to service RPC handlers
 * @param [in] hg_context Mercury context
Jonathan Jenkins's avatar
fixupme  
Jonathan Jenkins committed
68
 * @returns margo instance id on success, MARGO_INSTANCE_NULL upon error
69
 */
Shane Snyder's avatar
Shane Snyder committed
70 71 72
margo_instance_id margo_init_pool(
    ABT_pool progress_pool,
    ABT_pool handler_pool,
Jonathan Jenkins's avatar
Jonathan Jenkins committed
73
    hg_context_t *hg_context);
74 75

/**
Philip Carns's avatar
Philip Carns committed
76
 * Shuts down margo library and its underlying abt and mercury resources
Philip Carns's avatar
Philip Carns committed
77
 * @param [in] mid Margo instance
78
 */
79 80
void margo_finalize(
    margo_instance_id mid);
81 82 83 84 85 86 87 88 89 90 91

/**
 * Suspends the caller until some other entity (e.g. an RPC, thread, or
 * signal handler) invokes margo_finalize().
 *
 * NOTE: This informs Margo that the calling thread no longer needs to be 
 * scheduled for execution if it is sharing an Argobots pool with the
 * progress engine.
 *
 * @param [in] mid Margo instance
 */
92 93
void margo_wait_for_finalize(
    margo_instance_id mid);
94

95 96
/** 
 * Registers an RPC with margo
97 98 99 100 101 102 103 104
 *
 * \param [in] mid Margo instance
 * \param [in] func_name unique function name for RPC
 * \param [in] in_proc_cb pointer to input proc callback
 * \param [in] out_proc_cb pointer to output proc callback
 * \param [in] rpc_cb RPC callback
 *
 * \return unique ID associated to the registered function
105
 */
106 107 108 109 110 111
hg_id_t margo_register_name(
    margo_instance_id mid,
    const char *func_name,
    hg_proc_cb_t in_proc_cb,
    hg_proc_cb_t out_proc_cb,
    hg_rpc_cb_t rpc_cb);
112

113 114
/** 
 * Registers an RPC with margo that is associated with a multiplexed service
115 116 117 118 119 120 121 122 123 124
 *
 * \param [in] mid Margo instance
 * \param [in] func_name unique function name for RPC
 * \param [in] in_proc_cb pointer to input proc callback
 * \param [in] out_proc_cb pointer to output proc callback
 * \param [in] rpc_cb RPC callback
 * \param [in] mplex_id multiplexing identifier
 * \param [in] pool Argobots pool the handler will execute in
 *
 * \return unique ID associated to the registered function
125
 */
126 127 128 129 130 131 132 133
hg_id_t margo_register_name_mplex(
    margo_instance_id mid,
    const char *func_name,
    hg_proc_cb_t in_proc_cb,
    hg_proc_cb_t out_proc_cb,
    hg_rpc_cb_t rpc_cb,
    uint32_t mplex_id,
    ABT_pool pool);
134

135
/*
136
 * Indicate whether margo_register_name() has been called for the RPC specified by
137 138
 * func_name.
 *
139 140 141 142
 * \param [in] mid Margo instance
 * \param [in] func_name function name
 * \param [out] id registered RPC ID
 * \param [out] flag pointer to boolean
143 144
 *
 * \return HG_SUCCESS or corresponding HG error code
145
 */
146 147 148 149 150
hg_return_t margo_registered_name(
    margo_instance_id mid,
    const char *func_name,
    hg_id_t *id,
    hg_bool_t *flag);
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
/**
 * Register and associate user data to registered function.
 * When HG_Finalize() is called free_callback (if defined) is called 
 * to free the registered data.
 *
 * \param [in] mid            Margo instance
 * \param [in] id             registered function ID
 * \param [in] data           pointer to data
 * \param [in] free_callback  pointer to free function
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_register_data(
    margo_instance_id mid,
    hg_id_t id,
    void *data,
    void (*free_callback)(void *));

/**
 * Indicate whether margo_register_data() has been called and return associated
 * data.
 *
 * \param [in] mid        Margo instance 
 * \param [in] id         registered function ID
 *
 * \return Pointer to data or NULL
 */
179 180 181
void* margo_registered_data(
    margo_instance_id mid,
    hg_id_t id);
182 183

/**
184
 * Disable response for a given RPC ID.
185
 *
186 187 188
 * \param [in] mid          Margo instance 
 * \param [in] id           registered function ID
 * \param [in] disable_flag flag to disable (1) or re-enable (0) responses
189 190
 *
 * \return HG_SUCCESS or corresponding HG error code
191
 */
192 193 194 195
hg_return_t margo_registered_disable_response(
    margo_instance_id mid,
    hg_id_t id,
    int disable_flag);
196 197 198

/**
 * Lookup an addr from a peer address/name.
199 200 201 202
 * \param [in] name     lookup name
 * \param [out] addr    return address
 *
 * \return HG_SUCCESS or corresponding HG error code
203 204 205
 */
hg_return_t margo_addr_lookup(
    margo_instance_id mid,
206 207
    const char *name,
    hg_addr_t *addr);
208 209

/**
210
 * Free the given Mercury addr.
211
 *
212 213
 * \param [in] mid  Margo instance 
 * \param [in] addr Mercury address
214 215 216
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
217 218 219
hg_return_t margo_addr_free(
    margo_instance_id mid,
    hg_addr_t addr);
220 221

/**
222
 * Access self address. Address must be freed with margo_addr_free().
223
 *
224 225
 * \param [in] mid  Margo instance 
 * \param [in] addr pointer to abstract Mercury address
226 227 228
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
229 230 231
hg_return_t margo_addr_self(
    margo_instance_id mid,
    hg_addr_t *addr);
232 233

/**
234
 * Duplicate an existing Mercury address. 
235
 *
236 237 238
 * \param [in] mid      Margo instance 
 * \param [in] addr     abstract Mercury address to duplicate
 * \param [in] new_addr pointer to newly allocated abstract Mercury address
239 240 241
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
242 243 244 245
hg_return_t margo_addr_dup(
    margo_instance_id mid,
    hg_addr_t addr,
    hg_addr_t *new_addr);
246 247

/**
248 249 250 251 252
 * Convert a Mercury addr to a string (returned string includes the
 * terminating null byte '\0'). If buf is NULL, the address is not
 * converted and only the required size of the buffer is returned.
 * If the input value passed through buf_size is too small, HG_SIZE_ERROR
 * is returned and the buf_size output is set to the minimum size required.
253
 *
254 255 256 257
 * \param [in] mid          Margo instance 
 * \param [in/out] buf      pointer to destination buffer
 * \param [in/out] buf_size pointer to buffer size
 * \param [in] addr         abstract Mercury address
258 259 260
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
261 262 263 264 265
hg_return_t margo_addr_to_string(
    margo_instance_id mid,
    char *buf,
    hg_size_t *buf_size,
    hg_addr_t addr);
266 267

/**
268 269 270 271
 * Initiate a new Mercury RPC using the specified function ID and the
 * local/remote target defined by addr. The handle created can be used to
 * query input and output, as well as issuing the RPC by calling
 * HG_Forward(). After completion the handle must be freed using HG_Destroy().
272
 *
273 274 275 276
 * \param [in] mid      Margo instance 
 * \param [in] addr     abstract Mercury address of destination
 * \param [in] id       registered function ID
 * \param [out] handle  pointer to HG handle
277 278 279
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
280 281 282 283 284
hg_return_t margo_create(
    margo_instance_id mid,
    hg_addr_t addr,
    hg_id_t id,
    hg_handle_t *handle);
285 286

/**
287
 * Destroy Mercury handle.
288
 *
289
 * \param [in] handle Mercury handle
290 291 292
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
293 294
hg_return_t margo_destroy(
    hg_handle_t handle);
295 296

/**
297
 * Increment ref count on a Mercury handle.
298
 *
299
 * \param [in] handle Mercury handle
300 301 302
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
303 304
hg_return_t margo_ref_incr(
    hg_handle_t handle);
305 306 307 308

/**
 * Get info from handle.
 *
309
 * \param [in] handle Mercury handle
310 311 312
 *
 * \return Pointer to info or NULL in case of failure
 */
313 314
const struct hg_info *margo_get_info(
    hg_handle_t handle);
315 316 317

/**
 * Get input from handle (requires registration of input proc to deserialize
318
 * parameters). Input must be freed using margo_free_input().
319
 *
320 321
 * \param [in] handle           Mercury handle
 * \param [in/out] in_struct    pointer to input structure
322 323 324
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
325 326 327
hg_return_t margo_get_input(
    hg_handle_t handle,
    void *in_struct);
328 329 330 331

/**
 * Free resources allocated when deserializing the input.
 *
332 333
 * \param [in] handle           Mercury handle
 * \param [in/out] in_struct    pointer to input structure
334 335 336
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
337
hg_return_t margo_free_input(
338
        hg_handle_t handle,
339
        void *in_struct);
340 341 342

/**
 * Get output from handle (requires registration of output proc to deserialize
343
 * parameters). Output must be freed using margo_free_output().
344
 *
345 346
 * \param [in] handle           Mercury handle
 * \param [in/out] out_struct   pointer to output structure
347 348 349
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
350 351 352
hg_return_t margo_get_output(
    hg_handle_t handle,
    void *out_struct);
353 354 355 356

/**
 * Free resources allocated when deserializing the output.
 *
357 358
 * \param [in] handle           Mercury handle
 * \param [in/out] out_struct   pointer to output structure
359 360 361
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
362 363 364
hg_return_t margo_free_output(
    hg_handle_t handle,
    void *out_struct);
365

366 367
/**
 * Forward an RPC request to a remote host
Philip Carns's avatar
Philip Carns committed
368
 * @param [in] mid Margo instance
369 370 371 372 373
 * @param [in] handle identifier for the RPC to be sent
 * @param [in] in_struct input argument struct for RPC
 * @returns 0 on success, hg_return_t values on error
 */
hg_return_t margo_forward(
374
    margo_instance_id mid,
375 376 377
    hg_handle_t handle,
    void *in_struct);

378 379 380 381 382 383 384 385 386 387 388 389 390 391
/**
 * Forward an RPC request to a remote host with a user-defined timeout
 * @param [in] mid Margo instance
 * @param [in] handle identifier for the RPC to be sent
 * @param [in] in_struct input argument struct for RPC
 * @param [in] timeout_ms timeout in milliseconds
 * @returns 0 on success, hg_return_t values on error
 */
hg_return_t margo_forward_timed(
    margo_instance_id mid,
    hg_handle_t handle,
    void *in_struct,
    double timeout_ms);

Jonathan Jenkins's avatar
Jonathan Jenkins committed
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
/**
 * Send an RPC response, waiting for completion before returning
 * control to the calling ULT.
 * Note: this call is typically not needed as RPC listeners need not concern
 * themselves with what happens after an RPC finishes. However, there are cases
 * when this is useful (deferring resource cleanup, calling margo_finalize()
 * for e.g. a shutdown RPC).
 * @param [in] mid Margo instance
 * @param [in] handle identifier for the RPC for which a response is being
 * sent
 * @param [in] out_struct output argument struct for response
 * @return HG_SUCCESS on success, hg_return_t values on error. See HG_Respond.
 */
hg_return_t margo_respond(
    margo_instance_id mid,
    hg_handle_t handle,
    void *out_struct);

410 411 412
/**
 * Cancel an ongoing operation.
 *
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
 * \param [in] handle Mercury handle
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_cancel(
    hg_handle_t handle);

/**
 * Create an abstract bulk handle from specified memory segments.
 * Memory allocated is then freed when margo_bulk_free() is called.
 * \remark If NULL is passed to buf_ptrs, i.e.,
 * \verbatim margo_bulk_create(mid, count, NULL, buf_sizes, flags, &handle) \endverbatim
 * memory for the missing buf_ptrs array will be internally allocated.
 *
 * \param [in] mid          Margo instance 
 * \param [in] count        number of segments
 * \param [in] buf_ptrs     array of pointers
 * \param [in] buf_sizes    array of sizes
 * \param [in] flags        permission flag:
 *                             - HG_BULK_READWRITE
 *                             - HG_BULK_READ_ONLY
 *                             - HG_BULK_WRITE_ONLY
 * \param [out] handle      pointer to returned abstract bulk handle
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_bulk_create(
    margo_instance_id mid,
    hg_uint32_t count,
    void **buf_ptrs,
    const hg_size_t *buf_sizes,
    hg_uint8_t flags,
    hg_bulk_t *handle);

/**
 * Free bulk handle.
 *
 * \param [in/out] handle   abstract bulk handle
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_bulk_free(
    hg_bulk_t handle);

/**
 * Increment ref count on bulk handle.
 *
 * \param handle [IN]           abstract bulk handle
461 462 463
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
hg_return_t margo_bulk_ref_incr(
    hg_bulk_t handle);

/**
 * Access bulk handle to retrieve memory segments abstracted by handle.
 *
 * \param [in] handle           abstract bulk handle
 * \param [in] offset           bulk offset
 * \param [in] size             bulk size
 * \param [in] flags            permission flag:
 *                                 - HG_BULK_READWRITE
 *                                 - HG_BULK_READ_ONLY
 * \param [in] max_count        maximum number of segments to be returned
 * \param [in/out] buf_ptrs     array of buffer pointers
 * \param [in/out] buf_sizes    array of buffer sizes
 * \param [out] actual_count    actual number of segments returned
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_bulk_access(
    hg_bulk_t handle,
    hg_size_t offset,
    hg_size_t size,
    hg_uint8_t flags,
    hg_uint32_t max_count,
    void **buf_ptrs,
    hg_size_t *buf_sizes,
    hg_uint32_t *actual_count);

/**
 * Get total size of data abstracted by bulk handle.
 *
 * \param [in] handle   abstract bulk handle
 *
 * \return Non-negative value
 */
hg_size_t margo_bulk_get_size(
    hg_bulk_t handle);

/**
 * Get total number of segments abstracted by bulk handle.
 *
 * \param [in] handle   abstract bulk handle
 *
 * \return Non-negative value
 */
hg_uint32_t margo_bulk_get_segment_count(
    hg_bulk_t handle);

/**
 * Get size required to serialize bulk handle.
 *
 * \param [in] handle           abstract bulk handle
 * \param [in] request_eager    boolean (passing HG_TRUE adds size of encoding
 *                              actual data along the handle if handle meets
 *                              HG_BULK_READ_ONLY flag condition)
 *
 * \return Non-negative value
 */
hg_size_t margo_bulk_get_serialize_size(
    hg_bulk_t handle,
    hg_bool_t request_eager);

/**
 * Serialize bulk handle into a buffer.
 *
 * \param [in/out] buf          pointer to buffer
 * \param [in] buf_size         buffer size
 * \param [in] request_eager    boolean (passing HG_TRUE encodes actual data
 *                              along the handle, which is more efficient for
 *                              small data, this is only valid if bulk handle
 *                              has HG_BULK_READ_ONLY permission)
 * \param [in] handle           abstract bulk handle
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_bulk_serialize(
    void *buf,
    hg_size_t buf_size,
    hg_bool_t request_eager,
    hg_bulk_t handle);

/**
 * Deserialize bulk handle from an existing buffer.
 *
 * \param [in] mid      Margo instance 
 * \param [out] handle  abstract bulk handle
 * \param [in] buf      pointer to buffer
 * \param [in] buf_size buffer size
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_bulk_deserialize(
    margo_instance_id mid,
    hg_bulk_t *handle,
    const void *buf,
    hg_size_t buf_size);
561

562 563
/** 
 * Perform a bulk transfer
Philip Carns's avatar
Philip Carns committed
564
 * @param [in] mid Margo instance
565 566 567 568 569 570 571
 * @param [in] op type of operation to perform
 * @param [in] origin_addr remote Mercury address
 * @param [in] origin_handle remote Mercury bulk memory handle
 * @param [in] origin_offset offset into remote bulk memory to access
 * @param [in] local_handle local bulk memory handle
 * @param [in] local_offset offset into local bulk memory to access
 * @param [in] size size (in bytes) of transfer
572
 * @param [out] op_id pointer to returned operation ID
573 574 575
 * @returns 0 on success, hg_return_t values on error
 */
hg_return_t margo_bulk_transfer(
576
    margo_instance_id mid,
577
    hg_bulk_op_t op,
578
    hg_addr_t origin_addr,
579 580 581 582
    hg_bulk_t origin_handle,
    size_t origin_offset,
    hg_bulk_t local_handle,
    size_t local_offset,
583 584 585 586 587 588 589 590 591 592 593 594
    size_t size,
    hg_op_id_t *op_id);

/**
 * Cancel an ongoing operation.
 *
 * \param [in] op_id    operation ID
 *
 * \return HG_SUCCESS or corresponding HG error code
 */
hg_return_t margo_bulk_cancel(
    hg_op_id_t op_id);
595

596 597 598 599 600 601 602 603
/**
 * Suspends the calling ULT for a specified time duration
 * @param [in] mid Margo instance
 * @param [in] timeout_ms timeout duration in milliseconds
 */
void margo_thread_sleep(
    margo_instance_id mid,
    double timeout_ms);
604

605
/**
606 607 608
 * Retrieve the abt_handler pool that was associated with the instance at 
 *    initialization time
 * @param [in] mid Margo instance
609
 */
610
ABT_pool* margo_get_handler_pool(margo_instance_id mid);
611

612
/**
613 614
 * Retrieve the Mercury context that was associated with this instance at
 *    initialization time
615
 * @param [in] mid Margo instance
616
 * @return the Mercury context used in margo_init
617
 */
618
hg_context_t* margo_get_context(margo_instance_id mid);
619

620 621 622
/**
 * Retrieve the Mercury class that was associated with this instance at
 *    initialization time
623
 * @param [in] mid Margo instance
624
 * @return the Mercury class used in margo_init
625
 */
626
hg_class_t* margo_get_class(margo_instance_id mid);
627

628 629 630 631 632 633 634 635 636
/**
 * Get the margo_instance_id from a received RPC handle.
 *
 * \param [in] h          RPC handle
 * 
 * \return Margo instance
 */
margo_instance_id margo_hg_handle_get_instance(hg_handle_t h);

Philip Carns's avatar
Philip Carns committed
637 638 639 640 641 642 643 644 645
/**
 * Maps an RPC id and mplex id to the pool that it should execute on
 * @param [in] mid Margo instance
 * @param [in] id Mercury RPC identifier
 * @param [in] mplex_id multiplexing identifier
 * @param [out] pool Argobots pool the handler will execute in
 */
int margo_lookup_mplex(margo_instance_id mid, hg_id_t id, uint32_t mplex_id, ABT_pool *pool);

646 647 648 649 650

/**
 * macro that registers a function as an RPC.
 */
#define MARGO_REGISTER(__mid, __func_name, __in_t, __out_t, __handler, __rpc_id_ptr) do { \
651 652 653 654 655
    hg_id_t __id = margo_register_name( \
                       __mid, __func_name, \
                       BOOST_PP_CAT(hg_proc_, __in_t), \
                       BOOST_PP_CAT(hg_proc_, __out_t), \
                       __handler##_handler); \
656 657 658 659 660 661
    if(__rpc_id_ptr != MARGO_RPC_ID_IGNORE) { \
        *(__rpc_id_ptr) = __id; \
    } \
} while(0)

#define MARGO_REGISTER_MPLEX(__mid, __func_name, __in_t, __out_t, __handler, __mplex_id, __pool, __rpc_id_ptr) do { \
662 663 664 665 666 667
    hg_id_t __id = margo_register_name_mplex( \
                       __mid, __func_name, \
                       BOOST_PP_CAT(hg_proc_, __in_t), \
                       BOOST_PP_CAT(hg_proc_, __out_t), \
                       __handler##_handler, \
                       __mplex_id, __pool); \
668 669 670
    if(__rpc_id_ptr != MARGO_RPC_ID_IGNORE) { \
        *(__rpc_id_ptr) = __id; \
    } \
671 672
} while(0)

673 674
#define NULL_handler NULL

675
/**
Philip Carns's avatar
Philip Carns committed
676
 * macro that defines a function to glue an RPC handler to a ult handler
677 678
 * @param [in] __name name of handler function
 */
679
#define DEFINE_MARGO_RPC_HANDLER(__name) \
680
hg_return_t __name##_handler(hg_handle_t handle) { \
681
    int __ret; \
Philip Carns's avatar
Philip Carns committed
682
    ABT_pool __pool; \
683
    margo_instance_id __mid; \
Shane Snyder's avatar
Shane Snyder committed
684
    const struct hg_info *__hgi; \
685
    __hgi = HG_Get_info(handle); \
686 687 688 689
	__mid = margo_hg_handle_get_instance(handle); \
    if(__mid == MARGO_INSTANCE_NULL) { \
        return(HG_OTHER_ERROR); \
    } \
690
    __ret = margo_lookup_mplex(__mid, __hgi->id, __hgi->target_id, (&__pool)); \
Philip Carns's avatar
Philip Carns committed
691 692 693 694
    if(__ret != 0) { \
        return(HG_INVALID_PARAM); \
    }\
    __ret = ABT_thread_create(__pool, (void (*)(void *))__name, handle, ABT_THREAD_ATTR_NULL, NULL); \
695 696 697 698 699 700
    if(__ret != 0) { \
        return(HG_NOMEM_ERROR); \
    } \
    return(HG_SUCCESS); \
}

Philip Carns's avatar
Philip Carns committed
701 702
/**
 * macro that declares the prototype for a function to glue an RPC 
Philip Carns's avatar
Philip Carns committed
703
 * handler to a ult
Philip Carns's avatar
Philip Carns committed
704 705
 * @param [in] __name name of handler function
 */
706
#define DECLARE_MARGO_RPC_HANDLER(__name) hg_return_t __name##_handler(hg_handle_t handle);
707

708 709 710 711
#ifdef __cplusplus
}
#endif

712
#endif /* __MARGO */