shm_helper.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright 2020 ByteDance Games, Inc. All Rights Reserved.
  3. *
  4. * Author: Liuziming <liuziming.kelvin@bytedance.com>
  5. */
  6. #pragma once
  7. #include <stdint.h>
  8. #include <stddef.h>
  9. #include <string.h>
  10. #include <assert.h>
  11. #include <utility>
  12. #include <unordered_map>
  13. #ifndef _MSC_VER
  14. #define SHM_LIKELY(exp) __builtin_expect(!!(exp), 1)
  15. #define SHM_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
  16. #define SHM_FORCE_INLINE __attribute__((always_inline))
  17. #else
  18. #define SHM_LIKELY(exp) (exp)
  19. #define SHM_UNLIKELY(exp) !(exp)
  20. #define SHM_FORCE_INLINE
  21. #endif
  22. namespace bg {
  23. enum ShmLogLevel {
  24. SHM_LOG_TRACE = 0,
  25. SHM_LOG_DEBUG,
  26. SHM_LOG_INFO,
  27. SHM_LOG_WARN,
  28. SHM_LOG_ERROR,
  29. SHM_LOG_FATAL
  30. };
  31. using ShmLogger = void(ShmLogLevel level, const char* file, size_t line, const char* func, const char* msg);
  32. namespace detail {
  33. class ShmManager;
  34. class TypeName;
  35. void ShmLog(ShmLogLevel level, const char* file, size_t line, const char* func, const char* fmt, ...);/* __attribute__((format(printf, 5, 6)));*/
  36. void ShmStdoutLog(ShmLogLevel level, const char* file, size_t line, const char* func, const char* msg);
  37. void* ShmAllocate(size_t bytes, const void*);
  38. void ShmDeallocate(void* ptr, size_t);
  39. uint64_t ShmCurrentVersion();
  40. void* ShmAllocateRawMemory(size_t* bytes, size_t alignment);
  41. bool ShmHasSingleton(const TypeName& type);
  42. void* ShmGetSingleton(const TypeName& type, size_t bytes, bool* first_call);
  43. void ShmFreeSingleton(const TypeName& type);
  44. class TypeName {
  45. public:
  46. explicit TypeName(const char* type, size_t size = 0);
  47. const char* data() const { return m_type; }
  48. size_t length() const { return strnlen(m_type, MAX_TYPE_NAME_LENGTH); }
  49. const char* c_str() const { return m_type; }
  50. bool operator<(const TypeName& that) const {
  51. return strncmp(m_type, that.m_type, MAX_TYPE_NAME_LENGTH) < 0;
  52. }
  53. bool operator==(const TypeName& that) const {
  54. return strncmp(m_type, that.m_type, MAX_TYPE_NAME_LENGTH) == 0;
  55. }
  56. bool operator!=(const TypeName& that) const {
  57. return strncmp(m_type, that.m_type, MAX_TYPE_NAME_LENGTH) != 0;
  58. }
  59. private:
  60. static const size_t MAX_TYPE_NAME_LENGTH = 1024;
  61. char m_type[MAX_TYPE_NAME_LENGTH];
  62. };
  63. struct TypeNameHasher {
  64. size_t operator()(const TypeName& type) const {
  65. return std::_Fnv1a_append_value(type.length(), type.data());
  66. }
  67. };
  68. struct ShmContext {
  69. ShmLogger* logger = ShmStdoutLog;
  70. ShmManager* mgr = nullptr;
  71. size_t mmap_size = 0;
  72. char path[256];
  73. ShmContext() {
  74. memset(path, 0x00, sizeof(path));
  75. }
  76. };
  77. template<typename T>
  78. struct VptrHelper {
  79. struct D : public T {
  80. // NOTE: The destructor is not required, it's added to avoid compiler warning.
  81. virtual ~D() = default;
  82. virtual void IntroduceVptr() {}
  83. };
  84. static const bool value = std::is_polymorphic<T>::value || (sizeof(D) == sizeof(T));
  85. };
  86. template<typename T>
  87. struct HasVptr : public std::integral_constant<bool, VptrHelper<T>::value> {};
  88. template<typename T>
  89. class ShmAllocator {
  90. public:
  91. typedef size_t size_type;
  92. typedef ptrdiff_t difference_type;
  93. typedef T* pointer;
  94. typedef const T* const_pointer;
  95. typedef T& reference;
  96. typedef const T& const_reference;
  97. typedef T value_type;
  98. template<typename U>
  99. struct rebind {
  100. typedef ShmAllocator<U> other;
  101. };
  102. ShmAllocator() = default;
  103. template<typename U>
  104. explicit ShmAllocator(const ShmAllocator<U>&) {}
  105. pointer address(reference x) const { return &x; }
  106. const_pointer address(const_reference x) const { return &x; }
  107. size_type max_size() const { return size_t(-1) / sizeof(T); }
  108. void construct(pointer p, const T& val) { ::new(p) T(val); }
  109. void construct(pointer p) { ::new(p) T(); }
  110. void destroy(pointer p) { p->~T(); }
  111. // This is the C++11 version of construct.
  112. template<typename U, typename... Args>
  113. void construct(U* u, Args&&... args) { ::new(u) U(std::forward<Args>(args)...); }
  114. // This is the C++11 version of destroy.
  115. template<typename U>
  116. void destroy(U* u) { u->~U(); }
  117. bool operator==(const ShmAllocator&) const { return true; }
  118. bool operator!=(const ShmAllocator&) const { return false; }
  119. pointer allocate(size_type n, const void* ptr = nullptr) {
  120. return static_cast<value_type*>(ShmAllocate(n * sizeof(value_type), ptr));
  121. }
  122. void deallocate(pointer ptr, size_type size = 0) {
  123. ShmDeallocate(ptr, size);
  124. }
  125. };
  126. } // namespace detail
  127. } // namespace bg
  128. #define __SHM_LOG(level, fmt, ...) bg::detail::ShmLog(level, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
  129. #define SHM_TRACE(fmt, ...) __SHM_LOG(bg::SHM_LOG_TRACE, fmt, ##__VA_ARGS__)
  130. #define SHM_DEBUG(fmt, ...) __SHM_LOG(bg::SHM_LOG_DEBUG, fmt, ##__VA_ARGS__)
  131. #define SHM_INFO(fmt, ...) __SHM_LOG(bg::SHM_LOG_INFO, fmt, ##__VA_ARGS__)
  132. #define SHM_WARN(fmt, ...) __SHM_LOG(bg::SHM_LOG_WARN, fmt, ##__VA_ARGS__)
  133. #define SHM_ERROR(fmt, ...) __SHM_LOG(bg::SHM_LOG_ERROR, fmt, ##__VA_ARGS__)
  134. #define SHM_FATAL(fmt, ...) __SHM_LOG(bg::SHM_LOG_FATAL, fmt, ##__VA_ARGS__)
  135. // TODO: print stack trace here
  136. #define __SHM_DO_ASSERT(exp) \
  137. SHM_FATAL("assertion failure: %s", #exp); \
  138. assert(exp)
  139. #define SHM_ASSERT(exp) \
  140. do { \
  141. if (SHM_LIKELY(exp)) break; \
  142. __SHM_DO_ASSERT(exp); \
  143. } while (0)
  144. #define SHM_ASSERT_RETURN_VALUE(exp, val) \
  145. do { \
  146. if (SHM_LIKELY(exp)) break; \
  147. __SHM_DO_ASSERT(exp); \
  148. return (val); \
  149. } while (0)
  150. #define SHM_ASSERT_RETURN_VOID(exp) \
  151. do { \
  152. if (SHM_LIKELY(exp)) break; \
  153. __SHM_DO_ASSERT(exp); \
  154. return; \
  155. } while (0)
  156. #define SHM_ASSERT_RETURN_NULL(exp) SHM_ASSERT_RETURN_VALUE(exp, nullptr)
  157. #define SHM_ASSERT_RETURN_TRUE(exp) SHM_ASSERT_RETURN_VALUE(exp, true)
  158. #define SHM_ASSERT_RETURN_FALSE(exp) SHM_ASSERT_RETURN_VALUE(exp, false)
  159. #ifdef NDEBUG
  160. #define SHM_DEBUG_ASSERT(exp)
  161. #else
  162. #define SHM_DEBUG_ASSERT(exp) SHM_ASSERT(exp)
  163. #endif