ua_util.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #ifndef UA_UTIL_H_
  5. #define UA_UTIL_H_
  6. #include "ua_types.h"
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /* BSD Queue Macros */
  11. #include "queue.h"
  12. /* Macro-Expand for MSVC workarounds */
  13. #define UA_MACRO_EXPAND(x) x
  14. /* Thread-Local Storage
  15. * --------------------
  16. * Thread-local variables are always enabled. Also when the library is built
  17. * with ``UA_ENABLE_MULTITHREADING`` disabled. Otherwise, if multiple clients
  18. * run in separate threads, race conditions may occur via global variables in
  19. * the encoding layer. */
  20. #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
  21. # define UA_THREAD_LOCAL _Thread_local /* C11 */
  22. #elif defined(__cplusplus) && __cplusplus > 199711L
  23. # define UA_THREAD_LOCAL thread_local /* C++11 */
  24. #elif defined(__GNUC__)
  25. # define UA_THREAD_LOCAL __thread /* GNU extension */
  26. #elif defined(_MSC_VER)
  27. # define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
  28. #else
  29. # warning The compiler does not support thread-local variables
  30. # define UA_THREAD_LOCAL
  31. #endif
  32. /* Integer Shortnames
  33. * ------------------
  34. * These are not exposed on the public API, since many user-applications make
  35. * the same definitions in their headers. */
  36. typedef UA_Byte u8;
  37. typedef UA_SByte i8;
  38. typedef UA_UInt16 u16;
  39. typedef UA_Int16 i16;
  40. typedef UA_UInt32 u32;
  41. typedef UA_Int32 i32;
  42. typedef UA_UInt64 u64;
  43. typedef UA_Int64 i64;
  44. typedef UA_StatusCode status;
  45. /* Atomic Operations
  46. * -----------------
  47. * Atomic operations that synchronize across processor cores (for
  48. * multithreading). Only the inline-functions defined next are used. Replace
  49. * with architecture-specific operations if necessary. */
  50. #ifndef UA_ENABLE_MULTITHREADING
  51. # define UA_atomic_sync()
  52. #else
  53. # ifdef _MSC_VER /* Visual Studio */
  54. # define UA_atomic_sync() _ReadWriteBarrier()
  55. # else /* GCC/Clang */
  56. # define UA_atomic_sync() __sync_synchronize()
  57. # endif
  58. #endif
  59. static UA_INLINE void *
  60. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  61. #ifndef UA_ENABLE_MULTITHREADING
  62. void *old = *addr;
  63. *addr = newptr;
  64. return old;
  65. #else
  66. # ifdef _MSC_VER /* Visual Studio */
  67. return _InterlockedExchangePointer(addr, newptr);
  68. # else /* GCC/Clang */
  69. return __sync_lock_test_and_set(addr, newptr);
  70. # endif
  71. #endif
  72. }
  73. static UA_INLINE void *
  74. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  75. #ifndef UA_ENABLE_MULTITHREADING
  76. void *old = *addr;
  77. if(old == expected) {
  78. *addr = newptr;
  79. }
  80. return old;
  81. #else
  82. # ifdef _MSC_VER /* Visual Studio */
  83. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  84. # else /* GCC/Clang */
  85. return __sync_val_compare_and_swap(addr, expected, newptr);
  86. # endif
  87. #endif
  88. }
  89. static UA_INLINE uint32_t
  90. UA_atomic_add(volatile uint32_t *addr, uint32_t increase) {
  91. #ifndef UA_ENABLE_MULTITHREADING
  92. *addr += increase;
  93. return *addr;
  94. #else
  95. # ifdef _MSC_VER /* Visual Studio */
  96. return _InterlockedExchangeAdd(addr, increase) + increase;
  97. # else /* GCC/Clang */
  98. return __sync_add_and_fetch(addr, increase);
  99. # endif
  100. #endif
  101. }
  102. /* Utility Functions
  103. * ----------------- */
  104. /* Convert given byte string to a positive number. Returns the number of valid
  105. * digits. Stops if a non-digit char is found and returns the number of digits
  106. * up to that point. */
  107. size_t UA_readNumber(u8 *buf, size_t buflen, u32 *number);
  108. #define MIN(A,B) (A > B ? B : A)
  109. #define MAX(A,B) (A > B ? A : B)
  110. #ifdef UA_DEBUG_DUMP_PKGS
  111. void UA_EXPORT UA_dump_hex_pkg(UA_Byte* buffer, size_t bufferLen);
  112. #endif
  113. #ifdef __cplusplus
  114. } // extern "C"
  115. #endif
  116. #endif /* UA_UTIL_H_ */