00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef CUFLOW_CACHED_H
00019 #define CUFLOW_CACHED_H
00020
00021 #include <cuflow/fwd.h>
00022 #include <cuflow/sched.h>
00023 #include <cuflow/cdisj.h>
00024 #include <cu/conf.h>
00025 #include <cu/inherit.h>
00026 #include <atomic_ops.h>
00027
00028 CU_BEGIN_DECLARATIONS
00029
00030
00031
00032 typedef unsigned long cuflow_gain_t;
00033 typedef cu_clop0(cuflow_cached_clop_t, void);
00034
00035 typedef struct cuflowP_cached_node cuflowP_cached_node_t;
00036 struct cuflowP_cached_node
00037 {
00038 cuflowP_cached_node_t *next;
00039 AO_t cdisj;
00040 unsigned int access_ticks;
00041 cuflow_gain_t access_function;
00042 cuflow_gain_t access_gain;
00043 };
00044
00045 #define CUFLOW_CACHED_GRAN_SIZEW 1
00046 #define CUFLOW_CACHED_GRAN_SIZEB (CU_WORD_SIZE*CUFLOW_CACHED_GRAN_SIZEW)
00047 #define CUFLOW_CACHED_ARG_SIZEG(NAME) \
00048 ((sizeof(struct NAME##_arg) + CUFLOW_CACHED_GRAN_SIZEB - 1) \
00049 / CUFLOW_CACHED_GRAN_SIZEB)
00050 #define CUFLOW_CACHED_ARG_SIZE(NAME) \
00051 (CUFLOW_CACHED_ARG_SIZEG(NAME)*CUFLOW_CACHED_GRAN_SIZEB)
00052
00053 #define cuflowP_cached_decls(NAME, arg_members, res_members, linkage) \
00054 typedef struct NAME##_node NAME##_node_t; \
00055 \
00056 typedef struct NAME##_arg { \
00057 void (*fn)(struct NAME##_arg *); \
00058 cuPP_splice arg_members \
00059 } NAME##_arg_t; \
00060 \
00061 typedef union NAME##_u { \
00062 struct NAME##_arg arg; \
00063 char cuL_padding[CUFLOW_CACHED_ARG_SIZE(NAME)]; \
00064 } NAME##_t; \
00065 \
00066 typedef struct NAME##_result { \
00067 cuPP_splice res_members \
00068 } *NAME##_result_t; \
00069 \
00070 struct NAME##_node { \
00071 cu_inherit (cuflowP_cached_node); \
00072 NAME##_t padded_arg; \
00073 struct NAME##_result res; \
00074 }; \
00075 \
00076 linkage void NAME##_fn(NAME##_arg_t *arg); \
00077 \
00078 CU_SINLINE void \
00079 NAME##_init(NAME##_t *padded_arg) \
00080 { \
00081 memset(padded_arg, 0, CUFLOW_CACHED_ARG_SIZE(NAME)); \
00082 padded_arg->arg.fn = NAME##_fn; \
00083 } \
00084 \
00085 typedef NAME##_node_t *NAME##_promise_t; \
00086 \
00087 CU_SINLINE NAME##_result_t \
00088 NAME##_fulfill(NAME##_promise_t promise) \
00089 { \
00090 cuflow_cdisj_wait_while(&cu_to(cuflowP_cached_node, promise)->cdisj);\
00091 return &promise->res; \
00092 } \
00093 \
00094 CU_END_BOILERPLATE
00095
00096
00097
00098 #define cuflow_cached_edecl(NAME, arg_members, res_members) \
00099 cuflowP_cached_decls(NAME, arg_members, res_members, extern)
00100
00101
00102
00103 #define cuflow_cached_edef(NAME) \
00104 extern void NAME##_fn(NAME##_arg_t *arg)
00105
00106
00107
00108 #define cuflow_cached_sdecl(NAME, arg_members, res_members) \
00109 cuflowP_cached_decls(NAME, arg_members, res_members, static)
00110
00111
00112
00113 #define cuflow_cached_sdef(NAME) \
00114 static void NAME##_fn(NAME##_arg_t *arg)
00115
00116
00117
00118
00119 #define cuflow_cached_def(NAME, arg_members, res_members) \
00120 cuflow_cached_sdecl(NAME, arg_members, res_members); \
00121 cuflow_cached_sdef(NAME)
00122
00123 #define CUFLOW_CACHED_NODE_FROM_ARG(NAME, arg) \
00124 ((NAME##_node_t *) \
00125 ((char *)(arg) - offsetof(struct NAME##_node, padded_arg)))
00126
00127
00128
00129
00130
00131 #define cuflow_cached_arg_res(NAME) \
00132 NAME##_result_t res = &CUFLOW_CACHED_NODE_FROM_ARG(NAME, arg)->res
00133
00134 #define cuflow_cached_set_gain(NAME, x) \
00135 (cu_to(cuflowP_cached_node, \
00136 CUFLOW_CACHED_NODE_FROM_ARG(NAME, arg))->access_gain = x)
00137
00138 void *cuflowP_cached_call(void *arg, size_t arg_sizeg, size_t full_size);
00139 void *cuflowP_sched_cached_call(void *arg, size_t, size_t);
00140
00141 #define cuflow_cached_call(NAME, arg_block, result_out) \
00142 do { \
00143 NAME##_t cuL_padded_arg; \
00144 NAME##_init(&cuL_padded_arg); \
00145 NAME##_arg_t *arg = &cuL_padded_arg.arg; \
00146 { cuPP_splice arg_block } \
00147 { \
00148 NAME##_node_t *cuL_node = cuflowP_cached_call( \
00149 &cuL_padded_arg, CUFLOW_CACHED_ARG_SIZEG(NAME), \
00150 sizeof(struct NAME##_node)); \
00151 *(result_out) = &cuL_node->res; \
00152 } \
00153 } while (0)
00154
00155 #define cuflow_cached_sched_call(NAME, arg_block, promise_out) \
00156 do { \
00157 NAME##_t cuL_padded_arg; \
00158 NAME##_init(&cuL_padded_arg); \
00159 NAME##_arg_t *arg = &cuL_padded_arg.arg; \
00160 { cuPP_splice arg_block } \
00161 *(promise_out) = (NAME##_promise_t)cuflowP_sched_cached_call( \
00162 &cuL_padded_arg, CUFLOW_CACHED_ARG_SIZEG(NAME), \
00163 sizeof(struct NAME##_node)); \
00164 } while (0)
00165
00166
00167 CU_END_DECLARATIONS
00168
00169 #endif