#ifndef ATOMIC_OBJECT_INL_H_ #error "Direct inclusion of this file is not allowed, include atomic_object.h" // For the sake of sane code completion. #include "atomic_object.h" #endif namespace NYT::NThreading { //////////////////////////////////////////////////////////////////////////////// template template TAtomicObject::TAtomicObject(U&& u) : Object_(std::forward(u)) { } template template void TAtomicObject::Store(U&& u) { // NB: Using exchange to avoid destructing the old object while holding the lock. std::ignore = Exchange(std::forward(u)); } template template T TAtomicObject::Exchange(U&& u) { T tmpObject = std::forward(u); { auto guard = WriterGuard(Spinlock_); std::swap(Object_, tmpObject); } return tmpObject; } template bool TAtomicObject::CompareExchange(T& expected, const T& desired) { auto guard = WriterGuard(Spinlock_); if (Object_ == expected) { auto oldObject = std::move(Object_); Y_UNUSED(oldObject); Object_ = desired; guard.Release(); return true; } else { auto oldExpected = std::move(expected); Y_UNUSED(oldExpected); expected = Object_; guard.Release(); return false; } } template template F> std::invoke_result_t TAtomicObject::Transform(const F& func) { auto guard = WriterGuard(Spinlock_); return func(Object_); } template template F> std::invoke_result_t TAtomicObject::Read(const F& func) const { auto guard = ReaderGuard(Spinlock_); return func(Object_); } template T TAtomicObject::Load() const { auto guard = ReaderGuard(Spinlock_); return Object_; } //////////////////////////////////////////////////////////////////////////////// template void ToProto(TSerialized* serialized, const TAtomicObject& original) { ToProto(serialized, original.Load()); } template void FromProto(TAtomicObject* original, const TSerialized& serialized) { TOriginal data; FromProto(&data, serialized); original->Store(std::move(data)); } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NThreading