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