Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
refcount.h
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 00005 /*this header contains macros for ref_counting a variable. 00006 00007 There are no upper bound checks related to uint32_t overflow because we expect that bigger issues are in 00008 the system when more than 4 billion references exist to the same variable. In the case when such an overflow 00009 occurs, the object's ref count will reach zero (while still having 0xFFFFFFFF references) and likely the 00010 controlling code will take the decision to free the object's resources. Then, any of the 0xFFFFFFFF references 00011 will interact with deallocated memory / resources resulting in an undefined behavior. 00012 */ 00013 00014 #ifndef REFCOUNT_H 00015 #define REFCOUNT_H 00016 00017 #ifdef __cplusplus 00018 #include <cstdlib> 00019 #include <cstdint> 00020 extern "C" 00021 { 00022 #else 00023 #include <stdlib.h> 00024 #include <stdint.h> 00025 #endif 00026 00027 #include "azure_c_shared_utility/gballoc.h" 00028 #include "azure_c_shared_utility/macro_utils.h" 00029 00030 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ == 201112) && (__STDC_NO_ATOMICS__!=1) 00031 #define REFCOUNT_USE_STD_ATOMIC 1 00032 #endif 00033 00034 #if defined(ARDUINO_ARCH_SAMD) 00035 #undef REFCOUNT_USE_STD_ATOMIC 00036 #endif 00037 00038 #if defined(FREERTOS_ARCH_ESP8266) 00039 #undef REFCOUNT_USE_STD_ATOMIC 00040 #define REFCOUNT_ATOMIC_DONTCARE 1 00041 #undef __GNUC__ 00042 #endif 00043 00044 #define REFCOUNT_TYPE(type) \ 00045 struct C2(C2(REFCOUNT_, type), _TAG) 00046 00047 #define REFCOUNT_SHORT_TYPE(type) \ 00048 C2(REFCOUNT_, type) 00049 00050 #define REFCOUNT_TYPE_DECLARE_CREATE(type) C2(REFCOUNT_SHORT_TYPE(type), _Create) 00051 #define REFCOUNT_TYPE_CREATE(type) C2(REFCOUNT_SHORT_TYPE(type), _Create)() 00052 00053 /*this introduces a new refcount'd type based on another type */ 00054 /*and an initializer for that new type that also sets the ref count to 1. The type must not have a flexible array*/ 00055 /*the newly allocated memory shall be free'd by free()*/ 00056 /*and the ref counting is handled internally by the type in the _Create/ _Clone /_Destroy functions */ 00057 00058 #if defined(REFCOUNT_USE_STD_ATOMIC) 00059 #define COUNT_TYPE _Atomic uint32_t 00060 #elif defined(WIN32) 00061 #define COUNT_TYPE LONG 00062 #else 00063 #define COUNT_TYPE uint32_t 00064 #endif 00065 00066 #define DEFINE_REFCOUNT_TYPE(type) \ 00067 REFCOUNT_TYPE(type) \ 00068 { \ 00069 type counted; \ 00070 COUNT_TYPE count; \ 00071 }; \ 00072 static type* REFCOUNT_TYPE_DECLARE_CREATE(type) (void) \ 00073 { \ 00074 REFCOUNT_TYPE(type)* result = (REFCOUNT_TYPE(type)*)malloc(sizeof(REFCOUNT_TYPE(type))); \ 00075 if (result != NULL) \ 00076 { \ 00077 result->count = 1; \ 00078 } \ 00079 return (type*)result; \ 00080 } \ 00081 00082 /*the following macros increment/decrement a ref count in an atomic way, depending on the platform*/ 00083 /*The following mechanisms are considered in this order 00084 C11 00085 - will result in #include <stdatomic.h> 00086 - will use atomic_fetch_add/sub; 00087 - about the return value: "Atomically, the value pointed to by object immediately before the effects" 00088 windows 00089 - will result in #include "windows.h" 00090 - will use InterlockedIncrement/InterlockedDecrement; 00091 - about the return value: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683580(v=vs.85).aspx "The function returns the resulting decremented value" 00092 gcc 00093 - will result in no include (for gcc these are intrinsics build in) 00094 - will use __sync_fetch_and_add/sub 00095 - about the return value: "... returns the value that had previously been in memory." (https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html#Atomic-Builtins) 00096 other cases 00097 - if REFCOUNT_ATOMIC_DONTCARE is defined, then 00098 will result in ++/-- used for increment/decrement. 00099 - if it is not defined, then error out 00100 00101 It seems windows is "one off" because it returns the value "after" the decrement, as opposed to C11 standard and gcc that return the value "before". 00102 The macro DEC_RETURN_ZERO will be "0" on windows, and "1" on the other cases. 00103 */ 00104 00105 /*if macro DEC_REF returns DEC_RETURN_ZERO that means the ref count has reached zero.*/ 00106 #if defined(REFCOUNT_USE_STD_ATOMIC) 00107 #include <stdatomic.h> 00108 #define DEC_RETURN_ZERO (1) 00109 #define INC_REF(type, var) atomic_fetch_add((&((REFCOUNT_TYPE(type)*)var)->count), 1) 00110 #define DEC_REF(type, var) atomic_fetch_sub((&((REFCOUNT_TYPE(type)*)var)->count), 1) 00111 00112 #elif defined(WIN32) 00113 #include "windows.h" 00114 #define DEC_RETURN_ZERO (0) 00115 #define INC_REF(type, var) InterlockedIncrement(&(((REFCOUNT_TYPE(type)*)var)->count)) 00116 #define DEC_REF(type, var) InterlockedDecrement(&(((REFCOUNT_TYPE(type)*)var)->count)) 00117 00118 #elif defined(__GNUC__) 00119 #define DEC_RETURN_ZERO (0) 00120 #define INC_REF(type, var) __sync_add_and_fetch((&((REFCOUNT_TYPE(type)*)var)->count), 1) 00121 #define DEC_REF(type, var) __sync_sub_and_fetch((&((REFCOUNT_TYPE(type)*)var)->count), 1) 00122 00123 #else 00124 #if defined(REFCOUNT_ATOMIC_DONTCARE) 00125 #define DEC_RETURN_ZERO (0) 00126 #define INC_REF(type, var) ++((((REFCOUNT_TYPE(type)*)var)->count)) 00127 #define DEC_REF(type, var) --((((REFCOUNT_TYPE(type)*)var)->count)) 00128 #else 00129 #error do not know how to atomically increment and decrement a uint32_t :(. Platform support needs to be extended to your platform. 00130 #endif /*defined(REFCOUNT_ATOMIC_DONTCARE)*/ 00131 #endif 00132 00133 00134 00135 #ifdef __cplusplus 00136 } 00137 #endif 00138 00139 #endif /*REFCOUNT_H*/ 00140 00141
Generated on Tue Jul 12 2022 19:14:38 by
