codes-callback.h 3.52 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
*/

#ifndef CODES_CALLBACK_H
#define CODES_CALLBACK_H

Jonathan Jenkins's avatar
Jonathan Jenkins committed
10 11 12 13
#ifdef __cplusplus
extern "C" {
#endif

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#include <assert.h>
#include "codes/lp-msg.h"

/* This header defines the following conventions for callback-based event
 * processing (i.e., RPC-like event flow where the callee sends a "return
 * event" to the caller)
 *
 * callers:
 * - give the caller event size (for sanity checking)
 * - use the msg_header convention (lp-msg.h)
 * - specify an integer tag to identify which call the callee return event
 *   corresponds to, in the case of multiple pending callbacks
 * - specify an offset to the return structure, which is defined by the callees
 *
 * callees:
 * - use the resulting set of offsets to write and issue the callback
 *
 * The recommended calling convention for these types of event flows is:
32 33
 * void event_func(<params...>,
 *         msg_header const * h, int tag, struct codes_cb_info const * cb);
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
 */

struct codes_cb_info {
    int event_size;
    int header_offset;
    int tag_offset;
    int cb_ret_offset;
};

/* helper struct for callees - wrap up the typical inputs */
struct codes_cb_params {
    struct codes_cb_info info;
    msg_header h;
    int tag;
};

/* function-like sugar for initializing a codes_cb_info */
#define INIT_CODES_CB_INFO(_cb_info_ptr, _event_type, _header_field, _tag_field, _cb_ret_field) \
    do { \
        (_cb_info_ptr)->event_size    = sizeof(_event_type); \
        (_cb_info_ptr)->header_offset = offsetof(_event_type, _header_field); \
        (_cb_info_ptr)->tag_offset    = offsetof(_event_type, _tag_field); \
        (_cb_info_ptr)->cb_ret_offset = offsetof(_event_type, _cb_ret_field); \
    } while (0)

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
#define CB_HO(_cb_params_ptr) ((_cb_params_ptr)->info.header_offset)
#define CB_TO(_cb_params_ptr) ((_cb_params_ptr)->info.tag_offset)
#define CB_RO(_cb_params_ptr) ((_cb_params_ptr)->info.cb_ret_offset)

/* Declare return variables at the right byte offsets from a codes_cb_params.
 * Additionally, set the header and tag vars */
#define GET_INIT_CB_PTRS(_cb_params_ptr, _data_ptr, _sender_gid_val, _header_nm, _tag_nm, _rtn_name, _rtn_type) \
    msg_header * _header_nm = \
            (msg_header*)((char*)(_data_ptr) + CB_HO(_cb_params_ptr)); \
    int * _tag_nm = \
            (int*)((char*)(_data_ptr) + CB_TO(_cb_params_ptr));\
    _rtn_type * _rtn_name = \
            (_rtn_type*)((char*)(_data_ptr) + CB_RO(_cb_params_ptr)); \
    msg_set_header((_cb_params_ptr)->h.magic, (_cb_params_ptr)->h.event_type, \
            _sender_gid_val, _header_nm); \
    *_tag_nm = (_cb_params_ptr)->tag

76 77
#define SANITY_CHECK_CB(_cb_info_ptr, _ret_type) \
    do { \
Jonathan Jenkins's avatar
Jonathan Jenkins committed
78
        assert((_cb_info_ptr)->event_size > 0 && \
79 80 81
                (_cb_info_ptr)->header_offset >= 0 && \
                (_cb_info_ptr)->tag_offset >= 0 && \
                (_cb_info_ptr)->cb_ret_offset >= 0); \
Jonathan Jenkins's avatar
Jonathan Jenkins committed
82 83
        size_t _total_size = sizeof(_ret_type) + sizeof(int) + sizeof(msg_header);\
        size_t _esize = (_cb_info_ptr)->event_size; \
84 85 86 87 88 89
        assert(_esize >= _total_size); \
        assert(_esize >= (_cb_info_ptr)->header_offset + sizeof(msg_header)); \
        assert(_esize >= (_cb_info_ptr)->tag_offset + sizeof(int)); \
        assert(_esize >= (_cb_info_ptr)->cb_ret_offset + sizeof(_ret_type)); \
    } while (0)

Jonathan Jenkins's avatar
Jonathan Jenkins committed
90 91 92 93
#ifdef __cplusplus
}
#endif

94 95 96 97 98 99 100 101 102 103 104
#endif /* end of include guard: CODES_CALLBACK_H */

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  indent-tabs-mode: nil
 * End:
 *
 * vim: ft=c ts=8 sts=4 sw=4 expandtab
 */