atomic_object-inl.h 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #ifndef ATOMIC_OBJECT_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include atomic_object.h"
  3. // For the sake of sane code completion.
  4. #include "atomic_object.h"
  5. #endif
  6. namespace NYT::NThreading {
  7. ////////////////////////////////////////////////////////////////////////////////
  8. template <class T>
  9. template <class U>
  10. TAtomicObject<T>::TAtomicObject(U&& u)
  11. : Object_(std::forward<U>(u))
  12. { }
  13. template <class T>
  14. template <class U>
  15. void TAtomicObject<T>::Store(U&& u)
  16. {
  17. // NB: Using exchange to avoid destructing the old object while holding the lock.
  18. std::ignore = Exchange(std::forward<U>(u));
  19. }
  20. template <class T>
  21. template <class U>
  22. T TAtomicObject<T>::Exchange(U&& u)
  23. {
  24. T tmpObject = std::forward<U>(u);
  25. {
  26. auto guard = WriterGuard(Spinlock_);
  27. std::swap(Object_, tmpObject);
  28. }
  29. return tmpObject;
  30. }
  31. template <class T>
  32. bool TAtomicObject<T>::CompareExchange(T& expected, const T& desired)
  33. {
  34. auto guard = WriterGuard(Spinlock_);
  35. if (Object_ == expected) {
  36. auto oldObject = std::move(Object_);
  37. Y_UNUSED(oldObject);
  38. Object_ = desired;
  39. guard.Release();
  40. return true;
  41. } else {
  42. auto oldExpected = std::move(expected);
  43. Y_UNUSED(oldExpected);
  44. expected = Object_;
  45. guard.Release();
  46. return false;
  47. }
  48. }
  49. template <class T>
  50. template <std::invocable<T&> F>
  51. std::invoke_result_t<F, T&> TAtomicObject<T>::Transform(const F& func)
  52. {
  53. auto guard = WriterGuard(Spinlock_);
  54. return func(Object_);
  55. }
  56. template <class T>
  57. template <std::invocable<const T&> F>
  58. std::invoke_result_t<F, const T&> TAtomicObject<T>::Read(const F& func) const
  59. {
  60. auto guard = ReaderGuard(Spinlock_);
  61. return func(Object_);
  62. }
  63. template <class T>
  64. T TAtomicObject<T>::Load() const
  65. {
  66. auto guard = ReaderGuard(Spinlock_);
  67. return Object_;
  68. }
  69. ////////////////////////////////////////////////////////////////////////////////
  70. template <class TOriginal, class TSerialized>
  71. void ToProto(TSerialized* serialized, const TAtomicObject<TOriginal>& original)
  72. {
  73. ToProto(serialized, original.Load());
  74. }
  75. template <class TOriginal, class TSerialized>
  76. void FromProto(TAtomicObject<TOriginal>* original, const TSerialized& serialized)
  77. {
  78. TOriginal data;
  79. FromProto(&data, serialized);
  80. original->Store(std::move(data));
  81. }
  82. ////////////////////////////////////////////////////////////////////////////////
  83. } // namespace NYT::NThreading