Mark Radbourne / Mbed 2 deprecated iothub_client_sample_amqp

Dependencies:   EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed

Fork of iothub_client_sample_amqp by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers refcount.h Source File

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 
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 #define REFCOUNT_TYPE(type) \
00039 struct C2(C2(REFCOUNT_, type), _TAG)
00040 
00041 #define REFCOUNT_SHORT_TYPE(type) \
00042 C2(REFCOUNT_, type)
00043 
00044 #define REFCOUNT_TYPE_DECLARE_CREATE(type) C2(REFCOUNT_SHORT_TYPE(type), _Create)
00045 #define REFCOUNT_TYPE_CREATE(type) C2(REFCOUNT_SHORT_TYPE(type), _Create)()
00046 
00047 /*this introduces a new refcount'd type based on another type */
00048 /*and an initializer for that new type that also sets the ref count to 1. The type must not have a flexible array*/
00049 /*the newly allocated memory shall be free'd by free()*/
00050 /*and the ref counting is handled internally by the type in the _Create/ _Clone /_Destroy functions */
00051 
00052 #if defined(REFCOUNT_USE_STD_ATOMIC)
00053 #define COUNT_TYPE _Atomic uint32_t
00054 #elif defined(WIN32)
00055 #define COUNT_TYPE LONG
00056 #else
00057 #define COUNT_TYPE uint32_t
00058 #endif
00059 
00060 #define DEFINE_REFCOUNT_TYPE(type)                                                                   \
00061 REFCOUNT_TYPE(type)                                                                                  \
00062 {                                                                                                    \
00063     type counted;                                                                                    \
00064     COUNT_TYPE count;                                                                                  \
00065 };                                                                                                   \
00066 static type* REFCOUNT_TYPE_DECLARE_CREATE(type) (void)                                               \
00067 {                                                                                                    \
00068     REFCOUNT_TYPE(type)* result = (REFCOUNT_TYPE(type)*)malloc(sizeof(REFCOUNT_TYPE(type)));         \
00069     if (result != NULL)                                                                              \
00070     {                                                                                                \
00071         result->count = 1;                                                                           \
00072     }                                                                                                \
00073     return (type*)result;                                                                            \
00074 }                                                                                                    \
00075 
00076 /*the following macros increment/decrement a ref count in an atomic way, depending on the platform*/
00077 /*The following mechanisms are considered in this order
00078 C11 
00079     - will result in #include <stdatomic.h> 
00080     - will use atomic_fetch_add/sub; 
00081     - about the return value: "Atomically, the value pointed to by object immediately before the effects"
00082 windows 
00083     - will result in #include "windows.h"
00084     - will use InterlockedIncrement/InterlockedDecrement; 
00085     - 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"
00086 gcc
00087     - will result in no include (for gcc these are intrinsics build in)
00088     - will use __sync_fetch_and_add/sub
00089     - 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)
00090 other cases
00091     - if REFCOUNT_ATOMIC_DONTCARE is defined, then 
00092         will result in ++/-- used for increment/decrement.
00093     - if it is not defined, then error out
00094        
00095 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". 
00096 The macro DEC_RETURN_ZERO will be "0" on windows, and "1" on the other cases.
00097 */
00098 
00099 /*if macro DEC_REF returns DEC_RETURN_ZERO that means the ref count has reached zero.*/
00100 #if defined(REFCOUNT_USE_STD_ATOMIC)
00101 #include <stdatomic.h>
00102 #define DEC_RETURN_ZERO (1)
00103 #define INC_REF(type, var) atomic_fetch_add((&((REFCOUNT_TYPE(type)*)var)->count), 1)
00104 #define DEC_REF(type, var) atomic_fetch_sub((&((REFCOUNT_TYPE(type)*)var)->count), 1)
00105 
00106 #elif defined(WIN32)
00107 #include "windows.h"
00108 #define DEC_RETURN_ZERO (0)
00109 #define INC_REF(type, var) InterlockedIncrement(&(((REFCOUNT_TYPE(type)*)var)->count))
00110 #define DEC_REF(type, var) InterlockedDecrement(&(((REFCOUNT_TYPE(type)*)var)->count))
00111 
00112 #elif defined(__GNUC__)
00113 #define DEC_RETURN_ZERO (0)
00114 #define INC_REF(type, var) __sync_add_and_fetch((&((REFCOUNT_TYPE(type)*)var)->count), 1)
00115 #define DEC_REF(type, var) __sync_sub_and_fetch((&((REFCOUNT_TYPE(type)*)var)->count), 1)
00116 
00117 #else
00118 #if defined(REFCOUNT_ATOMIC_DONTCARE)
00119 #define DEC_RETURN_ZERO (0)
00120 #define INC_REF(type, var) ++((((REFCOUNT_TYPE(type)*)var)->count))
00121 #define DEC_REF(type, var) --((((REFCOUNT_TYPE(type)*)var)->count))
00122 #else
00123 #error do not know how to atomically increment and decrement a uint32_t :(. Platform support needs to be extended to your platform.
00124 #endif /*defined(REFCOUNT_ATOMIC_DONTCARE)*/
00125 #endif
00126 
00127 
00128 
00129 #ifdef __cplusplus
00130 }
00131 #endif
00132 
00133 #endif /*REFCOUNT_H*/
00134 
00135