File indexing completed on 2025-02-22 10:47:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 #ifndef PMIX_OBJECT_H
0123 #define PMIX_OBJECT_H
0124
0125 #include "src/include/pmix_config.h"
0126 #include "pmix_common.h"
0127
0128 #include <assert.h>
0129 #ifdef HAVE_STDLIB_H
0130 # include <stdlib.h>
0131 #endif
0132 #include <pthread.h>
0133 #include <stdio.h>
0134 #include <errno.h>
0135
0136 BEGIN_C_DECLS
0137
0138 #if PMIX_ENABLE_DEBUG
0139
0140 # define PMIX_OBJ_MAGIC_ID ((0xdeafbeedULL << 32) + 0xdeafbeedULL)
0141 #endif
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 #define PMIX_NEW_HAS_ARITY_HELPER(_1, _2, N, ...) N
0158
0159 #define PMIX_NEW_HAS_ARITY_IMPL(...) \
0160 PMIX_NEW_HAS_ARITY_HELPER(__VA_ARGS__)
0161
0162
0163
0164
0165
0166
0167
0168
0169 #define PMIX_CONSTRUCT_HAS_ARITY_HELPER(_1, _2, _3, N, ...) N
0170
0171 #define PMIX_CONSTRUCT_HAS_ARITY_IMPL(...) \
0172 PMIX_CONSTRUCT_HAS_ARITY_HELPER(__VA_ARGS__)
0173
0174
0175
0176
0177
0178
0179
0180 #define PMIX_NEW_HAS_ARGS_SOURCE() TMA, NO_TMA, ERROR
0181
0182 #define PMIX_CONSTRUCT_HAS_ARGS_SOURCE() TMA, NO_TMA, ERROR, ERROR
0183
0184 #define PMIX_OBJ_HAS_ARGS(...) \
0185 PMIX_NEW_HAS_ARITY_IMPL(__VA_ARGS__, PMIX_NEW_HAS_ARGS_SOURCE())
0186
0187 #define PMIX_CONSTRUCT_HAS_ARGS(...) \
0188 PMIX_CONSTRUCT_HAS_ARITY_IMPL(__VA_ARGS__, PMIX_CONSTRUCT_HAS_ARGS_SOURCE())
0189
0190
0191
0192
0193 #define PMIX_NEW_DISAMBIGUATE2(has_args, ...) \
0194 PMIX_NEW_ ## has_args (__VA_ARGS__)
0195
0196 #define PMIX_NEW_DISAMBIGUATE(has_args, ...) \
0197 PMIX_NEW_DISAMBIGUATE2(has_args, __VA_ARGS__)
0198
0199 #define PMIX_CONSTRUCT_DISAMBIGUATE2(has_args, ...) \
0200 PMIX_CONSTRUCT_ ## has_args (__VA_ARGS__)
0201
0202 #define PMIX_CONSTRUCT_DISAMBIGUATE(has_args, ...) \
0203 PMIX_CONSTRUCT_DISAMBIGUATE2(has_args, __VA_ARGS__)
0204
0205
0206
0207 typedef struct pmix_object_t pmix_object_t;
0208 typedef struct pmix_class_t pmix_class_t;
0209 typedef void (*pmix_construct_t)(pmix_object_t *);
0210 typedef void (*pmix_destruct_t)(pmix_object_t *);
0211
0212
0213
0214
0215 typedef struct pmix_tma {
0216
0217 void *(*tma_malloc)(struct pmix_tma *, size_t);
0218
0219 void *(*tma_calloc)(struct pmix_tma *, size_t, size_t);
0220
0221 void *(*tma_realloc)(struct pmix_tma *, void *, size_t);
0222
0223
0224
0225
0226
0227 char *(*tma_strdup)(struct pmix_tma *, const char *s);
0228
0229
0230
0231
0232
0233 void *(*tma_memmove)(struct pmix_tma *tma, const void *src, size_t n);
0234
0235 void (*tma_free)(struct pmix_tma *, void *);
0236
0237 void *data_context;
0238
0239
0240
0241
0242 void **data_ptr;
0243 } pmix_tma_t;
0244
0245 static inline void *pmix_tma_malloc(pmix_tma_t *tma, size_t size)
0246 {
0247 if (NULL != tma) {
0248 return tma->tma_malloc(tma, size);
0249 } else {
0250 return malloc(size);
0251 }
0252 }
0253
0254 static inline void *pmix_tma_calloc(pmix_tma_t *tma, size_t nmemb, size_t size)
0255 {
0256 if (NULL != tma) {
0257 return tma->tma_calloc(tma, nmemb, size);
0258 } else {
0259 return calloc(nmemb, size);
0260 }
0261 }
0262
0263 static inline void *pmix_tma_realloc(pmix_tma_t *tma, void *ptr, size_t size)
0264 {
0265 if (NULL != tma) {
0266 return tma->tma_realloc(tma, ptr, size);
0267 } else {
0268 return realloc(ptr, size);
0269 }
0270 }
0271
0272 static inline char *pmix_tma_strdup(pmix_tma_t *tma, const char *src)
0273 {
0274 if (NULL != tma) {
0275 return tma->tma_strdup(tma, src);
0276 } else {
0277 return strdup(src);
0278 }
0279 }
0280
0281 static inline void pmix_tma_free(pmix_tma_t *tma, void *ptr)
0282 {
0283 if (NULL != tma) {
0284 tma->tma_free(tma, ptr);
0285 } else {
0286 free(ptr);
0287 }
0288 }
0289
0290
0291
0292
0293
0294
0295
0296 struct pmix_class_t {
0297 const char *cls_name;
0298 pmix_class_t *cls_parent;
0299 pmix_construct_t cls_construct;
0300 pmix_destruct_t cls_destruct;
0301 int cls_initialized;
0302 int cls_depth;
0303 pmix_construct_t *cls_construct_array;
0304
0305 pmix_destruct_t *cls_destruct_array;
0306
0307 size_t cls_sizeof;
0308 };
0309
0310 PMIX_EXPORT extern int pmix_class_init_epoch;
0311
0312
0313
0314
0315
0316
0317 #if PMIX_ENABLE_DEBUG
0318 # define PMIX_OBJ_STATIC_INIT(BASE_CLASS) \
0319 { \
0320 .obj_magic_id = PMIX_OBJ_MAGIC_ID, \
0321 .obj_class = PMIX_CLASS(BASE_CLASS), \
0322 .obj_lock = PTHREAD_MUTEX_INITIALIZER, \
0323 .obj_reference_count = 1, \
0324 .obj_tma = { \
0325 .tma_malloc = NULL, \
0326 .tma_calloc = NULL, \
0327 .tma_realloc = NULL, \
0328 .tma_strdup = NULL, \
0329 .tma_memmove = NULL, \
0330 .tma_free = NULL, \
0331 .data_context = NULL, \
0332 .data_ptr = NULL \
0333 }, \
0334 .cls_init_file_name = __FILE__, \
0335 .cls_init_lineno = __LINE__ \
0336 }
0337 #else
0338 # define PMIX_OBJ_STATIC_INIT(BASE_CLASS) \
0339 { \
0340 .obj_class = PMIX_CLASS(BASE_CLASS), \
0341 .obj_lock = PTHREAD_MUTEX_INITIALIZER, \
0342 .obj_reference_count = 1, \
0343 .obj_tma = { \
0344 .tma_malloc = NULL, \
0345 .tma_calloc = NULL, \
0346 .tma_realloc = NULL, \
0347 .tma_strdup = NULL, \
0348 .tma_memmove = NULL, \
0349 .tma_free = NULL, \
0350 .data_context = NULL, \
0351 .data_ptr = NULL \
0352 } \
0353 }
0354 #endif
0355
0356
0357
0358
0359
0360
0361 struct pmix_object_t {
0362 #if PMIX_ENABLE_DEBUG
0363
0364
0365 uint64_t obj_magic_id;
0366 #endif
0367 pthread_mutex_t obj_lock;
0368 pmix_class_t *obj_class;
0369 int32_t obj_reference_count;
0370 pmix_tma_t obj_tma;
0371 #if PMIX_ENABLE_DEBUG
0372 const char *cls_init_file_name;
0373 int cls_init_lineno;
0374 #endif
0375 };
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 #define PMIX_CLASS(NAME) (&(NAME##_class))
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398 #define PMIX_CLASS_INSTANCE(NAME, PARENT, CONSTRUCTOR, DESTRUCTOR) \
0399 pmix_class_t NAME##_class = {#NAME, \
0400 PMIX_CLASS(PARENT), \
0401 (pmix_construct_t) CONSTRUCTOR, \
0402 (pmix_destruct_t) DESTRUCTOR, \
0403 0, \
0404 0, \
0405 NULL, \
0406 NULL, \
0407 sizeof(NAME)}
0408
0409
0410
0411
0412
0413
0414
0415
0416 #define PMIX_CLASS_DECLARATION(NAME) extern pmix_class_t NAME##_class
0417
0418
0419
0420
0421
0422
0423
0424
0425 static inline pmix_object_t *pmix_obj_new_tma(pmix_class_t *cls, pmix_tma_t *tma);
0426 #if PMIX_ENABLE_DEBUG
0427 static inline pmix_object_t *pmix_obj_new_debug_tma(pmix_class_t *type, pmix_tma_t *tma,
0428 const char *file, int line)
0429 {
0430 pmix_object_t *object = pmix_obj_new_tma(type, tma);
0431 if (NULL != object) {
0432 object->obj_magic_id = PMIX_OBJ_MAGIC_ID;
0433 object->cls_init_file_name = file;
0434 object->cls_init_lineno = line;
0435 }
0436 return object;
0437 }
0438
0439 #define PMIX_NEW_NO_TMA(type) \
0440 ((type *)pmix_obj_new_debug_tma(PMIX_CLASS(type), NULL, __FILE__, __LINE__))
0441
0442 #define PMIX_NEW_TMA(type, tma) \
0443 ((type *)pmix_obj_new_debug_tma(PMIX_CLASS(type), (tma), __FILE__, __LINE__))
0444
0445 #else
0446 #define PMIX_NEW_NO_TMA(type) ((type *)pmix_obj_new_tma(PMIX_CLASS(type), NULL))
0447
0448 #define PMIX_NEW_TMA(type, tma) ((type *)pmix_obj_new_tma(PMIX_CLASS(type), (tma)))
0449
0450 #endif
0451
0452
0453
0454
0455
0456
0457
0458 #define PMIX_NEW(...) \
0459 PMIX_NEW_DISAMBIGUATE(PMIX_OBJ_HAS_ARGS(__VA_ARGS__), __VA_ARGS__)
0460
0461
0462
0463
0464
0465
0466 #if PMIX_ENABLE_DEBUG
0467 # define PMIX_RETAIN(object) \
0468 do { \
0469 assert(NULL != ((pmix_object_t *) (object))->obj_class); \
0470 assert(PMIX_OBJ_MAGIC_ID == ((pmix_object_t *) (object))->obj_magic_id); \
0471 pmix_obj_update((pmix_object_t *) (object), 1); \
0472 assert(((pmix_object_t *) (object))->obj_reference_count >= 0); \
0473 } while (0)
0474 #else
0475 # define PMIX_RETAIN(object) pmix_obj_update((pmix_object_t *) (object), 1)
0476 #endif
0477
0478
0479
0480
0481
0482 #if PMIX_ENABLE_DEBUG
0483 # define PMIX_REMEMBER_FILE_AND_LINENO(OBJECT, FILE, LINENO) \
0484 do { \
0485 ((pmix_object_t *) (OBJECT))->cls_init_file_name = FILE; \
0486 ((pmix_object_t *) (OBJECT))->cls_init_lineno = LINENO; \
0487 } while (0)
0488 # define PMIX_SET_MAGIC_ID(OBJECT, VALUE) \
0489 do { \
0490 ((pmix_object_t *) (OBJECT))->obj_magic_id = (VALUE); \
0491 } while (0)
0492 #else
0493 # define PMIX_REMEMBER_FILE_AND_LINENO(OBJECT, FILE, LINENO)
0494 # define PMIX_SET_MAGIC_ID(OBJECT, VALUE)
0495 #endif
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507 #if PMIX_ENABLE_DEBUG
0508 # define PMIX_RELEASE(object) \
0509 do { \
0510 pmix_object_t *_obj = (pmix_object_t *) object; \
0511 assert(NULL != _obj->obj_class); \
0512 assert(PMIX_OBJ_MAGIC_ID == _obj->obj_magic_id); \
0513 if (0 == pmix_obj_update(_obj, -1)) { \
0514 PMIX_SET_MAGIC_ID((object), 0); \
0515 pmix_obj_run_destructors(_obj); \
0516 PMIX_REMEMBER_FILE_AND_LINENO(object, __FILE__, __LINE__); \
0517 if (NULL != _obj->obj_tma.tma_free) { \
0518 pmix_tma_free(&_obj->obj_tma, object); \
0519 } \
0520 else { \
0521 free(object); \
0522 } \
0523 object = NULL; \
0524 } \
0525 } while (0)
0526 #else
0527 # define PMIX_RELEASE(object) \
0528 do { \
0529 pmix_object_t *_obj = (pmix_object_t *) object; \
0530 if (0 == pmix_obj_update(_obj, -1)) { \
0531 pmix_obj_run_destructors(_obj); \
0532 if (NULL != _obj->obj_tma.tma_free) { \
0533 pmix_tma_free(&_obj->obj_tma, object); \
0534 } \
0535 else { \
0536 free(object); \
0537 } \
0538 object = NULL; \
0539 } \
0540 } while (0)
0541 #endif
0542
0543
0544
0545
0546
0547
0548
0549 static inline void pmix_obj_construct_tma(pmix_object_t *obj, pmix_tma_t *tma)
0550 {
0551 if (NULL == tma) {
0552 obj->obj_tma.tma_malloc = NULL;
0553 obj->obj_tma.tma_calloc = NULL;
0554 obj->obj_tma.tma_realloc = NULL;
0555 obj->obj_tma.tma_strdup = NULL;
0556 obj->obj_tma.tma_memmove = NULL;
0557 obj->obj_tma.tma_free = NULL;
0558 obj->obj_tma.data_context = NULL;
0559 obj->obj_tma.data_ptr = NULL;
0560 } else {
0561 obj->obj_tma = *tma;
0562 }
0563 }
0564
0565 #define PMIX_CONSTRUCT_INTERNAL_TMA(object, type, t) \
0566 do { \
0567 PMIX_SET_MAGIC_ID((object), PMIX_OBJ_MAGIC_ID); \
0568 if (pmix_class_init_epoch != (type)->cls_initialized) { \
0569 pmix_class_initialize((type)); \
0570 } \
0571 ((pmix_object_t *) (object))->obj_class = (type); \
0572 ((pmix_object_t *) (object))->obj_reference_count = 1; \
0573 pmix_obj_construct_tma(((pmix_object_t *) (object)), (t)); \
0574 pmix_obj_run_constructors((pmix_object_t *) (object)); \
0575 PMIX_REMEMBER_FILE_AND_LINENO(object, __FILE__, __LINE__); \
0576 } while (0)
0577
0578
0579 #define PMIX_CONSTRUCT_TMA(object, type, t) \
0580 do { \
0581 PMIX_CONSTRUCT_INTERNAL_TMA((object), PMIX_CLASS(type), (t)); \
0582 } while (0)
0583
0584
0585 #define PMIX_CONSTRUCT_NO_TMA(object, type) \
0586 do { \
0587 PMIX_CONSTRUCT_TMA(object, type, NULL); \
0588 } while (0)
0589
0590 #define PMIX_CONSTRUCT(...) \
0591 PMIX_CONSTRUCT_DISAMBIGUATE(PMIX_CONSTRUCT_HAS_ARGS(__VA_ARGS__), __VA_ARGS__)
0592
0593
0594
0595
0596
0597
0598 #if PMIX_ENABLE_DEBUG
0599 # define PMIX_DESTRUCT(object) \
0600 do { \
0601 assert(PMIX_OBJ_MAGIC_ID == ((pmix_object_t *) (object))->obj_magic_id); \
0602 PMIX_SET_MAGIC_ID((object), 0); \
0603 pmix_obj_run_destructors((pmix_object_t *) (object)); \
0604 PMIX_REMEMBER_FILE_AND_LINENO(object, __FILE__, __LINE__); \
0605 } while (0)
0606 #else
0607 # define PMIX_DESTRUCT(object) \
0608 do { \
0609 pmix_obj_run_destructors((pmix_object_t *) (object)); \
0610 PMIX_REMEMBER_FILE_AND_LINENO(object, __FILE__, __LINE__); \
0611 } while (0)
0612 #endif
0613
0614 PMIX_CLASS_DECLARATION(pmix_object_t);
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626 PMIX_EXPORT void pmix_class_initialize(pmix_class_t *cls);
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637 PMIX_EXPORT int pmix_class_finalize(void);
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651 static inline void pmix_obj_run_constructors(pmix_object_t *object)
0652 {
0653 pmix_construct_t *cls_construct;
0654
0655 assert(NULL != object->obj_class);
0656
0657 cls_construct = object->obj_class->cls_construct_array;
0658 while (NULL != *cls_construct) {
0659 (*cls_construct)(object);
0660 cls_construct++;
0661 }
0662 }
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672 static inline void pmix_obj_run_destructors(pmix_object_t *object)
0673 {
0674 pmix_destruct_t *cls_destruct;
0675
0676 assert(NULL != object->obj_class);
0677
0678 cls_destruct = object->obj_class->cls_destruct_array;
0679 while (NULL != *cls_destruct) {
0680 (*cls_destruct)(object);
0681 cls_destruct++;
0682 }
0683 }
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695 static inline pmix_object_t *pmix_obj_new_tma(pmix_class_t *cls, pmix_tma_t *tma)
0696 {
0697 pmix_object_t *object;
0698 assert(cls->cls_sizeof >= sizeof(pmix_object_t));
0699
0700 object = (pmix_object_t *) pmix_tma_malloc(tma, cls->cls_sizeof);
0701
0702 if (pmix_class_init_epoch != cls->cls_initialized) {
0703 pmix_class_initialize(cls);
0704 }
0705 if (NULL != object) {
0706 #if PMIX_ENABLE_DEBUG
0707 pthread_mutexattr_t attr;
0708 pthread_mutexattr_init(&attr);
0709
0710
0711 # if PMIX_HAVE_PTHREAD_MUTEX_ERRORCHECK_NP
0712 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
0713 # elif PMIX_HAVE_PTHREAD_MUTEX_ERRORCHECK
0714 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
0715 # endif
0716
0717 pthread_mutex_init(&object->obj_lock, &attr);
0718 pthread_mutexattr_destroy(&attr);
0719
0720 #else
0721
0722
0723 pthread_mutex_init(&object->obj_lock, NULL);
0724
0725 #endif
0726 object->obj_class = cls;
0727 object->obj_reference_count = 1;
0728 if (NULL == tma) {
0729 object->obj_tma.tma_malloc = NULL;
0730 object->obj_tma.tma_calloc = NULL;
0731 object->obj_tma.tma_realloc = NULL;
0732 object->obj_tma.tma_strdup = NULL;
0733 object->obj_tma.tma_free = NULL;
0734 object->obj_tma.data_context = NULL;
0735 object->obj_tma.data_ptr = NULL;
0736 } else {
0737 object->obj_tma = *tma;
0738 }
0739 pmix_obj_run_constructors(object);
0740 }
0741 return object;
0742 }
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754 static inline int pmix_obj_update(pmix_object_t *object, int inc) __pmix_attribute_always_inline__;
0755 static inline int pmix_obj_update(pmix_object_t *object, int inc)
0756 {
0757 int ret = pthread_mutex_lock(&object->obj_lock);
0758 if (ret == EDEADLK) {
0759 errno = ret;
0760 perror("pthread_mutex_lock()");
0761 abort();
0762 }
0763 ret = (object->obj_reference_count += inc);
0764 pthread_mutex_unlock(&object->obj_lock);
0765 return ret;
0766 }
0767
0768
0769
0770
0771
0772 static inline pmix_tma_t *
0773 pmix_obj_get_tma(
0774 pmix_object_t *obj
0775 ) {
0776
0777
0778 if (obj->obj_tma.tma_malloc) {
0779 return &obj->obj_tma;
0780 }
0781 return NULL;
0782 }
0783
0784 END_C_DECLS
0785
0786 #endif