variable-inl.h 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #ifndef GLOBAL_VARIABLE_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include variable.h"
  3. // For the sake of sane code completion.
  4. #include "variable.h"
  5. #endif
  6. namespace NYT::NGlobal {
  7. ////////////////////////////////////////////////////////////////////////////////
  8. template <CTriviallyErasable<GlobalVariableMaxByteSize> T>
  9. TVariable<T>::TVariable(
  10. const TVariableTag& tag,
  11. TAccessor accessor,
  12. T initValue) noexcept
  13. : Value_(initValue)
  14. {
  15. NDetail::RegisterVariable(tag, accessor);
  16. }
  17. template <CTriviallyErasable<GlobalVariableMaxByteSize> T>
  18. T TVariable<T>::Get() const noexcept
  19. {
  20. return Value_;
  21. }
  22. template <CTriviallyErasable<GlobalVariableMaxByteSize> T>
  23. void TVariable<T>::Set(T value) noexcept
  24. {
  25. Value_ = value;
  26. }
  27. ////////////////////////////////////////////////////////////////////////////////
  28. #undef YT_DEFINE_TRACKED_GLOBAL
  29. #undef YT_DEFINE_TRACKED_THREAD_LOCAL
  30. ////////////////////////////////////////////////////////////////////////////////
  31. #define YT_DEFINE_TRACKED_GLOBAL(Type, Name, Tag, InitExpr) \
  32. namespace NGlobalTracking##Name##Tag { \
  33. \
  34. ::NYT::NGlobal::TErasedStorage GetErased##Name() noexcept; \
  35. \
  36. static ::NYT::NGlobal::TVariable<Type> Name{Tag, GetErased##Name, (InitExpr)}; \
  37. \
  38. ::NYT::NGlobal::TErasedStorage GetErased##Name() noexcept \
  39. { \
  40. return ::NYT::NGlobal::TErasedStorage{Name.Get()}; \
  41. } \
  42. \
  43. } /*namespace NGlobalTracking##Name##Tag*/ \
  44. using NGlobalTracking##Name##Tag::Name; \
  45. static_assert(true)
  46. // NB(arkady-e1ppa): We must ensure that tracker is constructed thus
  47. // we have to call ref tracker inside tls accessor.
  48. // NB(arkady-e1ppa): Unlike normal static variable, we cannot just pull
  49. // varibale name out as we might want to forward-declare thread local variable
  50. // now that it is modelled as function. Pulling alias from ns unfortunately
  51. // doesn't work as function definition :(.
  52. #define YT_DEFINE_TRACKED_THREAD_LOCAL(Type, Name, Tag, ...) \
  53. Y_NO_INLINE Type& Name(); \
  54. namespace NGlobalTracking##Name##Tag { \
  55. \
  56. void EnsureTracked() noexcept; \
  57. ::NYT::NGlobal::TErasedStorage GetErased##Name() noexcept; \
  58. \
  59. static ::NYT::NGlobal::TVariable<std::byte> TlsTrackerFor##Name{Tag, GetErased##Name}; \
  60. \
  61. void EnsureTracked() noexcept \
  62. { \
  63. auto val = TlsTrackerFor##Name.Get(); \
  64. Y_UNUSED(val); \
  65. } \
  66. \
  67. ::NYT::NGlobal::TErasedStorage GetErased##Name() noexcept \
  68. { \
  69. return ::NYT::NGlobal::TErasedStorage{Name()}; \
  70. } \
  71. \
  72. } /*namespace NGlobalTracking##Name##Tag*/ \
  73. Y_NO_INLINE Type& Name() \
  74. { \
  75. thread_local Type tlsData { __VA_ARGS__ }; \
  76. asm volatile(""); \
  77. NGlobalTracking##Name##Tag::EnsureTracked(); \
  78. return tlsData; \
  79. } \
  80. \
  81. static_assert(true)
  82. ////////////////////////////////////////////////////////////////////////////////
  83. } // namespace NYT::NGlobal