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-2005 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2007 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) 2015 Los Alamos National Security, LLC. All rights
14 * reserved.
15 * $COPYRIGHT$
16 *
17 * Additional copyrights may follow
18 *
19 * $HEADER$
20 */
21
22 /**
23 * @file
24 *
25 * Implementation of opal_object_t, the base opal foundation class
26 */
27
28 #include "opal_config.h"
29
30 #include <stdio.h>
31
32 #include "opal/sys/atomic.h"
33 #include "opal/class/opal_object.h"
34 #include "opal/constants.h"
35
36 /*
37 * Instantiation of class descriptor for the base class. This is
38 * special, since be mark it as already initialized, with no parent
39 * and no constructor or destructor.
40 */
41 opal_class_t opal_object_t_class = {
42 "opal_object_t", /* name */
43 NULL, /* parent class */
44 NULL, /* constructor */
45 NULL, /* destructor */
46 1, /* initialized -- this class is preinitialized */
47 0, /* class hierarchy depth */
48 NULL, /* array of constructors */
49 NULL, /* array of destructors */
50 sizeof(opal_object_t) /* size of the opal object */
51 };
52
53 int opal_class_init_epoch = 1;
54
55 /*
56 * Local variables
57 */
58 static opal_atomic_lock_t class_lock = { { OPAL_ATOMIC_LOCK_UNLOCKED } };
59 static void** classes = NULL;
60 static int num_classes = 0;
61 static int max_classes = 0;
62 static const int increment = 10;
63
64
65 /*
66 * Local functions
67 */
68 static void save_class(opal_class_t *cls);
69 static void expand_array(void);
70
71
72 /*
73 * Lazy initialization of class descriptor.
74 */
opal_class_initialize(opal_class_t * cls)75 void opal_class_initialize(opal_class_t *cls)
76 {
77 opal_class_t *c;
78 opal_construct_t* cls_construct_array;
79 opal_destruct_t* cls_destruct_array;
80 int cls_construct_array_count;
81 int cls_destruct_array_count;
82 int i;
83
84 assert(cls);
85
86 /* Check to see if any other thread got in here and initialized
87 this class before we got a chance to */
88
89 if (opal_class_init_epoch == cls->cls_initialized) {
90 return;
91 }
92 opal_atomic_lock(&class_lock);
93
94 /* If another thread initializing this same class came in at
95 roughly the same time, it may have gotten the lock and
96 initialized. So check again. */
97
98 if (opal_class_init_epoch == cls->cls_initialized) {
99 opal_atomic_unlock(&class_lock);
100 return;
101 }
102
103 /*
104 * First calculate depth of class hierarchy
105 * And the number of constructors and destructors
106 */
107
108 cls->cls_depth = 0;
109 cls_construct_array_count = 0;
110 cls_destruct_array_count = 0;
111 for (c = cls; c; c = c->cls_parent) {
112 if( NULL != c->cls_construct ) {
113 cls_construct_array_count++;
114 }
115 if( NULL != c->cls_destruct ) {
116 cls_destruct_array_count++;
117 }
118 cls->cls_depth++;
119 }
120
121 /*
122 * Allocate arrays for hierarchy of constructors and destructors
123 * plus for each a NULL-sentinel
124 */
125
126 cls->cls_construct_array =
127 (void (**)(opal_object_t*))malloc((cls_construct_array_count +
128 cls_destruct_array_count + 2) *
129 sizeof(opal_construct_t) );
130 if (NULL == cls->cls_construct_array) {
131 perror("Out of memory");
132 exit(-1);
133 }
134 cls->cls_destruct_array =
135 cls->cls_construct_array + cls_construct_array_count + 1;
136
137 /*
138 * The constructor array is reversed, so start at the end
139 */
140
141 cls_construct_array = cls->cls_construct_array + cls_construct_array_count;
142 cls_destruct_array = cls->cls_destruct_array;
143
144 c = cls;
145 *cls_construct_array = NULL; /* end marker for the constructors */
146 for (i = 0; i < cls->cls_depth; i++) {
147 if( NULL != c->cls_construct ) {
148 --cls_construct_array;
149 *cls_construct_array = c->cls_construct;
150 }
151 if( NULL != c->cls_destruct ) {
152 *cls_destruct_array = c->cls_destruct;
153 cls_destruct_array++;
154 }
155 c = c->cls_parent;
156 }
157 *cls_destruct_array = NULL; /* end marker for the destructors */
158
159 cls->cls_initialized = opal_class_init_epoch;
160 save_class(cls);
161
162 /* All done */
163
164 opal_atomic_unlock(&class_lock);
165 }
166
167
168 /*
169 * Note that this is finalize for *all* classes.
170 */
opal_class_finalize(void)171 int opal_class_finalize(void)
172 {
173 int i;
174
175 if (INT_MAX == opal_class_init_epoch) {
176 opal_class_init_epoch = 1;
177 } else {
178 opal_class_init_epoch++;
179 }
180
181 if (NULL != classes) {
182 for (i = 0; i < num_classes; ++i) {
183 if (NULL != classes[i]) {
184 free(classes[i]);
185 }
186 }
187 free(classes);
188 classes = NULL;
189 num_classes = 0;
190 max_classes = 0;
191 }
192
193 return OPAL_SUCCESS;
194 }
195
196
save_class(opal_class_t * cls)197 static void save_class(opal_class_t *cls)
198 {
199 if (num_classes >= max_classes) {
200 expand_array();
201 }
202
203 classes[num_classes] = cls->cls_construct_array;
204 ++num_classes;
205 }
206
207
expand_array(void)208 static void expand_array(void)
209 {
210 int i;
211
212 max_classes += increment;
213 classes = (void**)realloc(classes, sizeof(opal_class_t*) * max_classes);
214 if (NULL == classes) {
215 perror("class malloc failed");
216 exit(-1);
217 }
218 for (i = num_classes; i < max_classes; ++i) {
219 classes[i] = NULL;
220 }
221 }
222
223