OpenMPI 0.1.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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 */
182 struct opal_object_t {
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 */
464 static inline opal_object_t *opal_obj_new(opal_class_t * cls)
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) {
471 opal_class_initialize(cls);
472 }
473 if (NULL != object) {
474 object->obj_class = cls;
475 object->obj_reference_count = 1;
476 opal_obj_run_constructors(object);
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
opal_class_t::cls_sizeof
size_t cls_sizeof
size of an object instance
Definition: opal_object.h:163
opal_class_t::cls_construct_array
opal_construct_t * cls_construct_array
array of parent class constructors
Definition: opal_object.h:159
opal_class_initialize
OPAL_DECLSPEC void opal_class_initialize(opal_class_t *)
Lazy initialization of class descriptor.
Definition: opal_object.c:70
opal_class_t::cls_destruct
opal_destruct_t cls_destruct
class destructor
Definition: opal_object.h:156
opal_obj_run_destructors
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
opal_object_t::obj_reference_count
volatile int32_t obj_reference_count
reference count
Definition: opal_object.h:189
opal_class_t::cls_name
const char * cls_name
symbolic name for class
Definition: opal_object.h:153
opal_class_t::cls_depth
int cls_depth
depth of class hierarchy tree
Definition: opal_object.h:158
opal_class_t
Class descriptor.
Definition: opal_object.h:152
opal_obj_new
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
opal_obj_update
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
opal_class_t::cls_initialized
int cls_initialized
is class initialized
Definition: opal_object.h:157
opal_class_t::cls_parent
opal_class_t * cls_parent
parent class descriptor
Definition: opal_object.h:154
opal_object_t
Base object.
Definition: opal_object.h:182
opal_class_finalize
OPAL_DECLSPEC int opal_class_finalize(void)
Shut down the class system and release all memory.
Definition: opal_object.c:166
opal_class_t::cls_destruct_array
opal_destruct_t * cls_destruct_array
array of parent class destructors
Definition: opal_object.h:161
atomic.h
Atomic operations.
opal_obj_run_constructors
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_class_t::cls_construct
opal_construct_t cls_construct
class constructor
Definition: opal_object.h:155
OBJ_CLASS_DECLARATION
#define OBJ_CLASS_DECLARATION(NAME)
Declaration for class descriptor.
Definition: opal_object.h:236
opal_object_t::obj_class
opal_class_t * obj_class
class descriptor
Definition: opal_object.h:188