root/opal/mca/pmix/pmix4x/pmix/src/class/pmix_object.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmix_class_initialize
  2. pmix_class_finalize
  3. save_class
  4. expand_array

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

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