root/opal/class/opal_object.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. opal_obj_new_debug
  2. opal_obj_run_constructors
  3. opal_obj_run_destructors
  4. opal_obj_new
  5. opal_obj_update

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2007 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2007-2014 Cisco Systems, Inc.  All rights reserved.
  14  * Copyright (c) 2014      Research Organization for Information Science
  15  *                         and Technology (RIST). All rights reserved.
  16  * Copyright (c) 2015      Los Alamos National Security, LLC. All rights
  17  *                         reserved.
  18  * $COPYRIGHT$
  19  * Additional copyrights may follow
  20  * $HEADER$
  21  */
  22 
  23 /**
  24  * @file:
  25  *
  26  * A simple C-language object-oriented system with single inheritance
  27  * and ownership-based memory management using a retain/release model.
  28  *
  29  * A class consists of a struct and singly-instantiated class
  30  * descriptor.  The first element of the struct must be the parent
  31  * class's struct.  The class descriptor must be given a well-known
  32  * name based upon the class struct name (if the struct is sally_t,
  33  * the class descriptor should be sally_t_class) and must be
  34  * statically initialized as discussed below.
  35  *
  36  * (a) To define a class
  37  *
  38  * In a interface (.h) file, define the class.  The first element
  39  * should always be the parent class, for example
  40  * @code
  41  *   struct sally_t
  42  *   {
  43  *     parent_t parent;
  44  *     void *first_member;
  45  *     ...
  46  *   };
  47  *   typedef struct sally_t sally_t;
  48  *
  49  *   OBJ_CLASS_DECLARATION(sally_t);
  50  * @endcode
  51  * All classes must have a parent which is also class.
  52  *
  53  * In an implementation (.c) file, instantiate a class descriptor for
  54  * the class like this:
  55  * @code
  56  *   OBJ_CLASS_INSTANCE(sally_t, parent_t, sally_construct, sally_destruct);
  57  * @endcode
  58  * This macro actually expands to
  59  * @code
  60  *   opal_class_t sally_t_class = {
  61  *     "sally_t",
  62  *     OBJ_CLASS(parent_t),  // pointer to parent_t_class
  63  *     sally_construct,
  64  *     sally_destruct,
  65  *     0, 0, NULL, NULL,
  66  *     sizeof ("sally_t")
  67  *   };
  68  * @endcode
  69  * This variable should be declared in the interface (.h) file using
  70  * the OBJ_CLASS_DECLARATION macro as shown above.
  71  *
  72  * sally_construct, and sally_destruct are function pointers to the
  73  * constructor and destructor for the class and are best defined as
  74  * static functions in the implementation file.  NULL pointers maybe
  75  * supplied instead.
  76  *
  77  * Other class methods may be added to the struct.
  78  *
  79  * (b) Class instantiation: dynamic
  80  *
  81  * To create a instance of a class (an object) use OBJ_NEW:
  82  * @code
  83  *   sally_t *sally = OBJ_NEW(sally_t);
  84  * @endcode
  85  * which allocates memory of sizeof(sally_t) and runs the class's
  86  * constructors.
  87  *
  88  * Use OBJ_RETAIN, OBJ_RELEASE to do reference-count-based
  89  * memory management:
  90  * @code
  91  *   OBJ_RETAIN(sally);
  92  *   OBJ_RELEASE(sally);
  93  *   OBJ_RELEASE(sally);
  94  * @endcode
  95  * When the reference count reaches zero, the class's destructor, and
  96  * those of its parents, are run and the memory is freed.
  97  *
  98  * N.B. There is no explicit free/delete method for dynamic objects in
  99  * this model.
 100  *
 101  * (c) Class instantiation: static
 102  *
 103  * For an object with static (or stack) allocation, it is only
 104  * necessary to initialize the memory, which is done using
 105  * OBJ_CONSTRUCT:
 106  * @code
 107  *   sally_t sally;
 108  *
 109  *   OBJ_CONSTRUCT(&sally, sally_t);
 110  * @endcode
 111  * The retain/release model is not necessary here, but before the
 112  * object goes out of scope, OBJ_DESTRUCT should be run to release
 113  * initialized resources:
 114  * @code
 115  *   OBJ_DESTRUCT(&sally);
 116  * @endcode
 117  */
 118 
 119 #ifndef OPAL_OBJECT_H
 120 #define OPAL_OBJECT_H
 121 
 122 #include "opal_config.h"
 123 #include <assert.h>
 124 #include <stdlib.h>
 125 
 126 #include "opal/threads/thread_usage.h"
 127 
 128 BEGIN_C_DECLS
 129 
 130 #if OPAL_ENABLE_DEBUG
 131 /* Any kind of unique ID should do the job */
 132 #define OPAL_OBJ_MAGIC_ID ((0xdeafbeedULL << 32) + 0xdeafbeedULL)
 133 #endif
 134 
 135 /* typedefs ***********************************************************/
 136 
 137 typedef struct opal_object_t opal_object_t;
 138 typedef struct opal_class_t opal_class_t;
 139 typedef void (*opal_construct_t) (opal_object_t *);
 140 typedef void (*opal_destruct_t) (opal_object_t *);
 141 
 142 
 143 /* types **************************************************************/
 144 
 145 /**
 146  * Class descriptor.
 147  *
 148  * There should be a single instance of this descriptor for each class
 149  * definition.
 150  */
 151 struct opal_class_t {
 152     const char *cls_name;           /**< symbolic name for class */
 153     opal_class_t *cls_parent;       /**< parent class descriptor */
 154     opal_construct_t cls_construct; /**< class constructor */
 155     opal_destruct_t cls_destruct;   /**< class destructor */
 156     int cls_initialized;            /**< is class initialized */
 157     int cls_depth;                  /**< depth of class hierarchy tree */
 158     opal_construct_t *cls_construct_array;
 159                                     /**< array of parent class constructors */
 160     opal_destruct_t *cls_destruct_array;
 161                                     /**< array of parent class destructors */
 162     size_t cls_sizeof;              /**< size of an object instance */
 163 };
 164 
 165 extern int opal_class_init_epoch;
 166 
 167 /**
 168  * For static initializations of OBJects.
 169  *
 170  * @param NAME   Name of the class to initialize
 171  */
 172 #if OPAL_ENABLE_DEBUG
 173 #define OPAL_OBJ_STATIC_INIT(BASE_CLASS)        \
 174     {                                           \
 175         .obj_magic_id = OPAL_OBJ_MAGIC_ID,      \
 176         .obj_class = OBJ_CLASS(BASE_CLASS),     \
 177         .obj_reference_count = 1,               \
 178         .cls_init_file_name = __FILE__,         \
 179         .cls_init_lineno = __LINE__,            \
 180     }
 181 #else
 182 #define OPAL_OBJ_STATIC_INIT(BASE_CLASS)        \
 183     {                                           \
 184         .obj_class = OBJ_CLASS(BASE_CLASS),     \
 185         .obj_reference_count = 1,               \
 186     }
 187 #endif
 188 
 189 /**
 190  * Base object.
 191  *
 192  * This is special and does not follow the pattern for other classes.
 193  */
 194 struct opal_object_t {
 195 #if OPAL_ENABLE_DEBUG
 196     /** Magic ID -- want this to be the very first item in the
 197         struct's memory */
 198     uint64_t obj_magic_id;
 199 #endif
 200     opal_class_t *obj_class;            /**< class descriptor */
 201     opal_atomic_int32_t obj_reference_count;   /**< reference count */
 202 #if OPAL_ENABLE_DEBUG
 203    const char* cls_init_file_name;        /**< In debug mode store the file where the object get contructed */
 204    int   cls_init_lineno;           /**< In debug mode store the line number where the object get contructed */
 205 #endif  /* OPAL_ENABLE_DEBUG */
 206 };
 207 
 208 /* macros ************************************************************/
 209 
 210 /**
 211  * Return a pointer to the class descriptor associated with a
 212  * class type.
 213  *
 214  * @param NAME          Name of class
 215  * @return              Pointer to class descriptor
 216  */
 217 #define OBJ_CLASS(NAME)     (&(NAME ## _class))
 218 
 219 
 220 /**
 221  * Static initializer for a class descriptor
 222  *
 223  * @param NAME          Name of class
 224  * @param PARENT        Name of parent class
 225  * @param CONSTRUCTOR   Pointer to constructor
 226  * @param DESTRUCTOR    Pointer to destructor
 227  *
 228  * Put this in NAME.c
 229  */
 230 #define OBJ_CLASS_INSTANCE(NAME, PARENT, CONSTRUCTOR, DESTRUCTOR)       \
 231     opal_class_t NAME ## _class = {                                     \
 232         # NAME,                                                         \
 233         OBJ_CLASS(PARENT),                                              \
 234         (opal_construct_t) CONSTRUCTOR,                                 \
 235         (opal_destruct_t) DESTRUCTOR,                                   \
 236         0, 0, NULL, NULL,                                               \
 237         sizeof(NAME)                                                    \
 238     }
 239 
 240 
 241 /**
 242  * Declaration for class descriptor
 243  *
 244  * @param NAME          Name of class
 245  *
 246  * Put this in NAME.h
 247  */
 248 #define OBJ_CLASS_DECLARATION(NAME)             \
 249     extern opal_class_t NAME ## _class
 250 
 251 
 252 /**
 253  * Create an object: dynamically allocate storage and run the class
 254  * constructor.
 255  *
 256  * @param type          Type (class) of the object
 257  * @return              Pointer to the object
 258  */
 259 static inline opal_object_t *opal_obj_new(opal_class_t * cls);
 260 #if OPAL_ENABLE_DEBUG
 261 static inline opal_object_t *opal_obj_new_debug(opal_class_t* type, const char* file, int line)
 262 {
 263     opal_object_t* object = opal_obj_new(type);
 264     object->obj_magic_id = OPAL_OBJ_MAGIC_ID;
 265     object->cls_init_file_name = file;
 266     object->cls_init_lineno = line;
 267     return object;
 268 }
 269 #define OBJ_NEW(type)                                   \
 270     ((type *)opal_obj_new_debug(OBJ_CLASS(type), __FILE__, __LINE__))
 271 #else
 272 #define OBJ_NEW(type)                                   \
 273     ((type *) opal_obj_new(OBJ_CLASS(type)))
 274 #endif  /* OPAL_ENABLE_DEBUG */
 275 
 276 /**
 277  * Retain an object (by incrementing its reference count)
 278  *
 279  * @param object        Pointer to the object
 280  */
 281 #if OPAL_ENABLE_DEBUG
 282 #define OBJ_RETAIN(object)                                              \
 283     do {                                                                \
 284         assert(NULL != ((opal_object_t *) (object))->obj_class);        \
 285         assert(OPAL_OBJ_MAGIC_ID == ((opal_object_t *) (object))->obj_magic_id); \
 286         opal_obj_update((opal_object_t *) (object), 1);                 \
 287         assert(((opal_object_t *) (object))->obj_reference_count >= 0); \
 288     } while (0)
 289 #else
 290 #define OBJ_RETAIN(object)  opal_obj_update((opal_object_t *) (object), 1);
 291 #endif
 292 
 293 /**
 294  * Helper macro for the debug mode to store the locations where the status of
 295  * an object change.
 296  */
 297 #if OPAL_ENABLE_DEBUG
 298 #define OBJ_REMEMBER_FILE_AND_LINENO( OBJECT, FILE, LINENO )    \
 299     do {                                                        \
 300         ((opal_object_t*)(OBJECT))->cls_init_file_name = FILE;  \
 301         ((opal_object_t*)(OBJECT))->cls_init_lineno = LINENO;   \
 302     } while(0)
 303 #define OBJ_SET_MAGIC_ID( OBJECT, VALUE )                       \
 304     do {                                                        \
 305         ((opal_object_t*)(OBJECT))->obj_magic_id = (VALUE);     \
 306     } while(0)
 307 #else
 308 #define OBJ_REMEMBER_FILE_AND_LINENO( OBJECT, FILE, LINENO )
 309 #define OBJ_SET_MAGIC_ID( OBJECT, VALUE )
 310 #endif  /* OPAL_ENABLE_DEBUG */
 311 
 312 /**
 313  * Release an object (by decrementing its reference count).  If the
 314  * reference count reaches zero, destruct (finalize) the object and
 315  * free its storage.
 316  *
 317  * Note: If the object is freed, then the value of the pointer is set
 318  * to NULL.
 319  *
 320  * @param object        Pointer to the object
 321  *
 322  *
 323  */
 324 #if OPAL_ENABLE_DEBUG
 325 #define OBJ_RELEASE(object)                                             \
 326     do {                                                                \
 327         assert(OPAL_OBJ_MAGIC_ID == ((opal_object_t *) (object))->obj_magic_id); \
 328         assert(NULL != ((opal_object_t *) (object))->obj_class);        \
 329         if (0 == opal_obj_update((opal_object_t *) (object), -1)) {     \
 330             OBJ_SET_MAGIC_ID((object), 0);                              \
 331             opal_obj_run_destructors((opal_object_t *) (object));       \
 332             OBJ_REMEMBER_FILE_AND_LINENO( object, __FILE__, __LINE__ ); \
 333             free(object);                                               \
 334             object = NULL;                                              \
 335         }                                                               \
 336     } while (0)
 337 #else
 338 #define OBJ_RELEASE(object)                                             \
 339     do {                                                                \
 340         if (0 == opal_obj_update((opal_object_t *) (object), -1)) {     \
 341             opal_obj_run_destructors((opal_object_t *) (object));       \
 342             free(object);                                               \
 343             object = NULL;                                              \
 344         }                                                               \
 345     } while (0)
 346 #endif
 347 
 348 
 349 /**
 350  * Construct (initialize) objects that are not dynamically allocated.
 351  *
 352  * @param object        Pointer to the object
 353  * @param type          The object type
 354  */
 355 
 356 #define OBJ_CONSTRUCT(object, type)                             \
 357 do {                                                            \
 358     OBJ_CONSTRUCT_INTERNAL((object), OBJ_CLASS(type));          \
 359 } while (0)
 360 
 361 #define OBJ_CONSTRUCT_INTERNAL(object, type)                        \
 362 do {                                                                \
 363     OBJ_SET_MAGIC_ID((object), OPAL_OBJ_MAGIC_ID);                  \
 364     if (opal_class_init_epoch != (type)->cls_initialized) {         \
 365         opal_class_initialize((type));                              \
 366     }                                                               \
 367     ((opal_object_t *) (object))->obj_class = (type);               \
 368     ((opal_object_t *) (object))->obj_reference_count = 1;          \
 369     opal_obj_run_constructors((opal_object_t *) (object));          \
 370     OBJ_REMEMBER_FILE_AND_LINENO( object, __FILE__, __LINE__ ); \
 371 } while (0)
 372 
 373 
 374 /**
 375  * Destruct (finalize) an object that is not dynamically allocated.
 376  *
 377  * @param object        Pointer to the object
 378  */
 379 #if OPAL_ENABLE_DEBUG
 380 #define OBJ_DESTRUCT(object)                                    \
 381 do {                                                            \
 382     assert(OPAL_OBJ_MAGIC_ID == ((opal_object_t *) (object))->obj_magic_id); \
 383     OBJ_SET_MAGIC_ID((object), 0);                              \
 384     opal_obj_run_destructors((opal_object_t *) (object));       \
 385     OBJ_REMEMBER_FILE_AND_LINENO( object, __FILE__, __LINE__ ); \
 386 } while (0)
 387 #else
 388 #define OBJ_DESTRUCT(object)                                    \
 389 do {                                                            \
 390     opal_obj_run_destructors((opal_object_t *) (object));       \
 391     OBJ_REMEMBER_FILE_AND_LINENO( object, __FILE__, __LINE__ ); \
 392 } while (0)
 393 #endif
 394 
 395 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_object_t);
 396 
 397 /* declarations *******************************************************/
 398 
 399 /**
 400  * Lazy initialization of class descriptor.
 401  *
 402  * Specifically cache arrays of function pointers for the constructor
 403  * and destructor hierarchies for this class.
 404  *
 405  * @param class    Pointer to class descriptor
 406  */
 407 OPAL_DECLSPEC void opal_class_initialize(opal_class_t *);
 408 
 409 /**
 410  * Shut down the class system and release all memory
 411  *
 412  * This function should be invoked as the ABSOLUTE LAST function to
 413  * use the class subsystem.  It frees all associated memory with ALL
 414  * classes, rendering all of them inoperable.  It is here so that
 415  * tools like valgrind and purify don't report still-reachable memory
 416  * upon process termination.
 417  */
 418 OPAL_DECLSPEC int opal_class_finalize(void);
 419 
 420 /**
 421  * Run the hierarchy of class constructors for this object, in a
 422  * parent-first order.
 423  *
 424  * Do not use this function directly: use OBJ_CONSTRUCT() instead.
 425  *
 426  * WARNING: This implementation relies on a hardwired maximum depth of
 427  * the inheritance tree!!!
 428  *
 429  * Hardwired for fairly shallow inheritance trees
 430  * @param size          Pointer to the object.
 431  */
 432 static inline void opal_obj_run_constructors(opal_object_t * object)
 433 {
 434     opal_construct_t* cls_construct;
 435 
 436     assert(NULL != object->obj_class);
 437 
 438     cls_construct = object->obj_class->cls_construct_array;
 439     while( NULL != *cls_construct ) {
 440         (*cls_construct)(object);
 441         cls_construct++;
 442     }
 443 }
 444 
 445 
 446 /**
 447  * Run the hierarchy of class destructors for this object, in a
 448  * parent-last order.
 449  *
 450  * Do not use this function directly: use OBJ_DESTRUCT() instead.
 451  *
 452  * @param size          Pointer to the object.
 453  */
 454 static inline void opal_obj_run_destructors(opal_object_t * object)
 455 {
 456     opal_destruct_t* cls_destruct;
 457 
 458     assert(NULL != object->obj_class);
 459 
 460     cls_destruct = object->obj_class->cls_destruct_array;
 461     while( NULL != *cls_destruct ) {
 462         (*cls_destruct)(object);
 463         cls_destruct++;
 464     }
 465 }
 466 
 467 
 468 /**
 469  * Create new object: dynamically allocate storage and run the class
 470  * constructor.
 471  *
 472  * Do not use this function directly: use OBJ_NEW() instead.
 473  *
 474  * @param size          Size of the object
 475  * @param cls           Pointer to the class descriptor of this object
 476  * @return              Pointer to the object
 477  */
 478 static inline opal_object_t *opal_obj_new(opal_class_t * cls)
 479 {
 480     opal_object_t *object;
 481     assert(cls->cls_sizeof >= sizeof(opal_object_t));
 482 
 483 #if OPAL_WANT_MEMCHECKER
 484     object = (opal_object_t *) calloc(1, cls->cls_sizeof);
 485 #else
 486     object = (opal_object_t *) malloc(cls->cls_sizeof);
 487 #endif
 488     if (opal_class_init_epoch != cls->cls_initialized) {
 489         opal_class_initialize(cls);
 490     }
 491     if (NULL != object) {
 492         object->obj_class = cls;
 493         object->obj_reference_count = 1;
 494         opal_obj_run_constructors(object);
 495     }
 496     return object;
 497 }
 498 
 499 
 500 /**
 501  * Atomically update the object's reference count by some increment.
 502  *
 503  * This function should not be used directly: it is called via the
 504  * macros OBJ_RETAIN and OBJ_RELEASE
 505  *
 506  * @param object        Pointer to the object
 507  * @param inc           Increment by which to update reference count
 508  * @return              New value of the reference count
 509  */
 510 static inline int opal_obj_update(opal_object_t *object, int inc) __opal_attribute_always_inline__;
 511 static inline int opal_obj_update(opal_object_t *object, int inc)
 512 {
 513     return OPAL_THREAD_ADD_FETCH32(&object->obj_reference_count, inc);
 514 }
 515 
 516 END_C_DECLS
 517 
 518 #endif

/* [<][>][^][v][top][bottom][index][help] */