1 /** 2 * Copyright (C) Mellanox Technologies Ltd. 2001-2014. ALL RIGHTS RESERVED. 3 * 4 * See file LICENSE for terms. 5 */ 6 7 #ifndef UCS_OBJECT_H_ 8 #define UCS_OBJECT_H_ 9 10 #include <ucs/sys/compiler_def.h> 11 #include <ucs/sys/preprocessor.h> 12 #include <ucs/type/status.h> 13 #include <stddef.h> 14 15 BEGIN_C_DECLS 16 17 /** @file class.h */ 18 19 typedef struct ucs_class ucs_class_t; 20 21 22 typedef ucs_status_t (*ucs_class_init_func_t) (void *self, ...); 23 typedef void (*ucs_class_cleanup_func_t)(void *self); 24 25 struct ucs_class { 26 const char *name; 27 size_t size; 28 ucs_class_t *superclass; 29 ucs_class_init_func_t init; 30 ucs_class_cleanup_func_t cleanup; 31 }; 32 33 34 /* 35 * Helper: Define names of class-related identifiers. 36 */ 37 #define UCS_CLASS_DECL_NAME(_type) \ 38 _UCS_CLASS_DECL_NAME(_type) 39 #define _UCS_CLASS_DECL_NAME(_type) \ 40 UCS_PP_TOKENPASTE(_type, _class) 41 #define _UCS_CLASS_INIT_NAME(_type) \ 42 UCS_PP_TOKENPASTE(_type, _init) 43 #define _UCS_CLASS_CLEANUP_NAME(_type) \ 44 UCS_PP_TOKENPASTE(_type, _cleanup) 45 46 /** 47 * Class initialization/cleanup function prototypes. 48 */ 49 #define UCS_CLASS_INIT_FUNC(_type, ...) \ 50 ucs_status_t _UCS_CLASS_INIT_NAME(_type)(_type *self, ucs_class_t *_myclass, \ 51 int *_init_count, ## __VA_ARGS__) 52 #define UCS_CLASS_CLEANUP_FUNC(_type) \ 53 void _UCS_CLASS_CLEANUP_NAME(_type)(_type *self) 54 55 56 /** 57 * Declare a class. 58 * 59 * @param _type Class type. 60 */ 61 #define UCS_CLASS_DECLARE(_type, ...) \ 62 extern ucs_class_t _UCS_CLASS_DECL_NAME(_type); \ 63 UCS_CLASS_INIT_FUNC(_type, ## __VA_ARGS__); 64 65 #define UCS_CLASS_NAME(_type) \ 66 _UCS_CLASS_DECL_NAME(_type) 67 68 /** 69 * Define a class. 70 * 71 * @param _type Class type. 72 * @param _super Superclass type (may be void to indicate top-level class) 73 */ 74 #define UCS_CLASS_DEFINE(_type, _super) \ 75 extern ucs_class_t _UCS_CLASS_DECL_NAME(_super); \ 76 ucs_class_t _UCS_CLASS_DECL_NAME(_type) = { \ 77 UCS_PP_QUOTE(_type), \ 78 sizeof(_type), \ 79 &_UCS_CLASS_DECL_NAME(_super), \ 80 (ucs_class_init_func_t)(_UCS_CLASS_INIT_NAME(_type)), \ 81 (ucs_class_cleanup_func_t)(_UCS_CLASS_CLEANUP_NAME(_type)) \ 82 }; 83 84 85 /** 86 * Initialize a class in-place. 87 * 88 * @param _type Class type. 89 * @param _obj Instance pointer to initialize. 90 * @param ... Additional arguments to the constructor. 91 * 92 * @return UCS_OK, or error code if failed. 93 */ 94 #define UCS_CLASS_INIT(_type, _obj, ...) \ 95 ({ \ 96 ucs_class_t *_cls = &_UCS_CLASS_DECL_NAME(_type); \ 97 int _init_counter = 1; \ 98 ucs_status_t __status; \ 99 \ 100 __status = _UCS_CLASS_INIT_NAME(_type)((_type*)(_obj), _cls, \ 101 &_init_counter, ## __VA_ARGS__); \ 102 if (__status != UCS_OK) { \ 103 ucs_class_call_cleanup_chain(&_UCS_CLASS_DECL_NAME(_type), \ 104 (_obj), _init_counter); \ 105 } \ 106 \ 107 (__status); \ 108 }) 109 110 111 /** 112 * Cleanup a class in-place. 113 * 114 * @param _type Class type. 115 * @param _obj Instance pointer to cleanup. 116 */ 117 #define UCS_CLASS_CLEANUP_CALL(_cls, _obj) \ 118 ucs_class_call_cleanup_chain(_cls, _obj, -1) 119 120 121 /** 122 * Cleanup a class in-place. 123 * 124 * @param _type Class type. 125 * @param _obj Instance pointer to cleanup. 126 */ 127 #define UCS_CLASS_CLEANUP(_type, _obj) \ 128 { \ 129 UCS_CLASS_CLEANUP_CALL(&_UCS_CLASS_DECL_NAME(_type), _obj); \ 130 } 131 132 133 /** 134 * Instantiate a class. 135 * 136 * @param _type Class type. 137 * @param _obj Variable to save the new instance to. 138 * @param ... Additional arguments to the constructor. 139 * 140 * @return UCS_OK, or error code if failed. 141 */ 142 #define UCS_CLASS_NEW(_type, _obj, ...) \ 143 _UCS_CLASS_NEW (_type, _obj, ## __VA_ARGS__) 144 #define _UCS_CLASS_NEW(_type, _obj, ...) \ 145 ({ \ 146 ucs_class_t *cls = &_UCS_CLASS_DECL_NAME(_type); \ 147 ucs_status_t _status; \ 148 void *obj; \ 149 \ 150 obj = ucs_class_malloc(cls); \ 151 if (obj != NULL) { \ 152 _status = UCS_CLASS_INIT(_type, obj, ## __VA_ARGS__); \ 153 if (_status == UCS_OK) { \ 154 *(_obj) = (typeof(*(_obj)))obj; /* Success - assign pointer */ \ 155 } else { \ 156 ucs_class_free(obj); /* Initialization failure */ \ 157 } \ 158 } else { \ 159 _status = UCS_ERR_NO_MEMORY; /* Allocation failure */ \ 160 } \ 161 \ 162 (_status); \ 163 }) 164 165 166 /** 167 * Destroy a class instance. 168 * 169 * @param _type Class type. 170 * @param _obj Instance to destroy. 171 */ 172 #define UCS_CLASS_DELETE(_type, _obj) \ 173 { \ 174 UCS_CLASS_CLEANUP(_type, _obj); \ 175 ucs_class_free(_obj); \ 176 } 177 178 179 /** 180 * Invoke the parent constructor. 181 * Should be used only from init function (which defines "self" and "_myclass") 182 * 183 * @param _superclass Type of the superclass. 184 * @param ... Arguments to parent constructor. 185 */ 186 #define UCS_CLASS_CALL_SUPER_INIT(_superclass, ...) \ 187 { \ 188 { \ 189 ucs_status_t _status = _UCS_CLASS_INIT_NAME(_superclass)\ 190 (&self->super, _myclass->superclass, _init_count, ## __VA_ARGS__); \ 191 if (_status != UCS_OK) { \ 192 return _status; \ 193 } \ 194 if (_myclass->superclass != &_UCS_CLASS_DECL_NAME(void)) { \ 195 ++(*_init_count); \ 196 } \ 197 } \ 198 } 199 200 201 /** 202 * Declare / define a function which creates an instance of a class. 203 * 204 * @param _name Function name. 205 * @param _type Class type. 206 * @param _argtype Type to use for the instance argument. Should be a superclass of _type. 207 * @param ... List of types for initialization arguments (without variable names). 208 * 209 * Defines a function which can be used as follows: 210 * { 211 * ucs_status_t status; 212 * _type *obj; 213 * status = _type##_new(arg1, arg2, arg3, &obj); 214 * } 215 */ 216 #define UCS_CLASS_DECLARE_NAMED_NEW_FUNC(_name, _argtype, ...) \ 217 ucs_status_t _name(UCS_PP_FOREACH(_UCS_CLASS_INIT_ARG_DEFINE, _, \ 218 UCS_PP_ZIP((UCS_PP_SEQ(UCS_PP_NUM_ARGS(__VA_ARGS__))), \ 219 (__VA_ARGS__))) \ 220 _argtype **obj_p) 221 #define UCS_CLASS_DEFINE_NAMED_NEW_FUNC(_name, _type, _argtype, ...) \ 222 UCS_CLASS_DECLARE_NAMED_NEW_FUNC(_name, _argtype, ## __VA_ARGS__) { \ 223 ucs_status_t status; \ 224 \ 225 *obj_p = NULL; \ 226 \ 227 status = UCS_CLASS_NEW(_type, obj_p \ 228 UCS_PP_FOREACH(_UCS_CLASS_INIT_ARG_PASS, _, \ 229 UCS_PP_SEQ(UCS_PP_NUM_ARGS(__VA_ARGS__)))); \ 230 ucs_class_check_new_func_result(status, *obj_p); \ 231 return status; \ 232 } 233 #define UCS_CLASS_DECLARE_NEW_FUNC(_type, _argtype, ...) \ 234 UCS_CLASS_DECLARE_NAMED_NEW_FUNC(UCS_CLASS_NEW_FUNC_NAME(_type), _argtype, ## __VA_ARGS__) 235 #define UCS_CLASS_DEFINE_NEW_FUNC(_type, _argtype, ...) \ 236 UCS_CLASS_DEFINE_NAMED_NEW_FUNC(UCS_CLASS_NEW_FUNC_NAME(_type), _type, _argtype, ## __VA_ARGS__) 237 238 239 /* 240 * Helper macros for creating argument list 241 */ 242 #define _UCS_CLASS_INIT_ARG_DEFINE(_, _bundle) \ 243 __UCS_CLASS_INIT_ARG_DEFINE(_, UCS_PP_TUPLE_0 _bundle, UCS_PP_TUPLE_1 _bundle) 244 #define __UCS_CLASS_INIT_ARG_DEFINE(_, _index, _type) \ 245 _type _UCS_CLASS_INIT_ARG_NAME(_, _index), 246 #define _UCS_CLASS_INIT_ARG_PASS(_, _index) \ 247 , _UCS_CLASS_INIT_ARG_NAME(_, _index) 248 #define _UCS_CLASS_INIT_ARG_NAME(_, _index) \ 249 UCS_PP_TOKENPASTE(arg, _index) 250 251 252 /** 253 * Name of the function created by UCS_CLASS_DEFINE_NEW_FUNC. 254 */ 255 #define UCS_CLASS_NEW_FUNC_NAME(_type) \ 256 UCS_PP_TOKENPASTE(_type, _new) 257 258 259 /** 260 * Define a function which deletes class instance. 261 * 262 * @param _type Class type. 263 * @param _argtype Type to use for the instance argument. Should be a superclass of _type. 264 * 265 * Defines a function which can be used as follows: 266 * { 267 * _type *obj = ...; 268 * _type##_delete(obj); 269 */ 270 #define UCS_CLASS_DECLARE_NAMED_DELETE_FUNC(_name, _argtype) \ 271 void _name(_argtype *self) 272 #define UCS_CLASS_DEFINE_NAMED_DELETE_FUNC(_name, _type, _argtype) \ 273 UCS_CLASS_DECLARE_NAMED_DELETE_FUNC(_name, _argtype) \ 274 { \ 275 UCS_CLASS_DELETE(_type, self); \ 276 } 277 #define UCS_CLASS_DECLARE_DELETE_FUNC(_type, _argtype) \ 278 UCS_CLASS_DECLARE_NAMED_DELETE_FUNC(UCS_CLASS_DELETE_FUNC_NAME(_type), _argtype) 279 #define UCS_CLASS_DEFINE_DELETE_FUNC(_type, _argtype) \ 280 UCS_CLASS_DEFINE_NAMED_DELETE_FUNC(UCS_CLASS_DELETE_FUNC_NAME(_type), _type, _argtype) 281 282 283 /** 284 * Name of the function created by UCS_CLASS_DEFINE_DELETE_FUNC. 285 */ 286 #define UCS_CLASS_DELETE_FUNC_NAME(_type) \ 287 UCS_PP_TOKENPASTE(_type, _delete) 288 289 290 /** 291 * Helper: Call class destructor chain. 292 * 293 * @param cls Class type. 294 * @param obj Instance pointer. 295 * @param limit How many destructors to call (0: none, -1: all, 1: only ucs_object_t's). 296 */ 297 void ucs_class_call_cleanup_chain(ucs_class_t *cls, void *obj, int limit); 298 299 300 /* 301 * Helpers: 302 */ 303 /* Allocate objects */ 304 void *ucs_class_malloc(ucs_class_t *cls); 305 /* Release objects */ 306 void ucs_class_free(void *obj); 307 /* Check new function result */ 308 void ucs_class_check_new_func_result(ucs_status_t status, void *obj); 309 310 311 /** 312 * The empty class. 313 */ 314 UCS_CLASS_DECLARE(void); 315 316 END_C_DECLS 317 318 #endif 319