userver: userver/utils/swappingsmart.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
swappingsmart.hpp
1#pragma once
2
3#include <atomic>
4#include <memory>
5
6USERVER_NAMESPACE_BEGIN
7
8namespace utils {
9
10// Use a faster and more reliable rcu::Variable instead of this class!
11//
12// This class helps to store pointer. Pointer stored as shared_ptr.
13// Whet you call Get, you will get copy of this shared pointer under read lock.
14// When you call Set pointer, it will be stored under writelock.
15//
16// It works slower than SwappingPtr in 5 times, but readers will always have
17// shared_ptr that they obtained, so it is impossible that data will be free'd.
18template <typename T>
19class SwappingSmart {
20 public:
21 SwappingSmart() = default;
22
23 explicit SwappingSmart(const std::shared_ptr<T>& ptr) { Set(ptr); }
24
25 std::shared_ptr<T> Get() const {
26 const short index = current_.load(std::memory_order_relaxed);
27 return ptrs_[index];
28 }
29 void Set(const std::shared_ptr<T>& ptr) {
30 std::shared_ptr<T> buf = ptr;
31 // wait for write lock
32 while (write_lock_.test_and_set(std::memory_order_acquire)) {
33 }
34 // read current index
35 const short index = current_.load(std::memory_order_relaxed);
36 // get new index
37 const short new_index = 1 - index;
38 // store data in new index
39 std::swap(ptrs_[new_index], buf);
40 // enable new index
41 current_.store(new_index, std::memory_order_relaxed);
42 // unlock write lock
43 write_lock_.clear(std::memory_order_release);
44 // old value will be cleaned here, after lock
45 }
46 void Set(T&& obj) { Set(std::make_shared<T>(std::move(obj))); }
47 void Clear() {
48 Set(std::make_shared<T>());
49 Set(std::make_shared<T>());
50 }
51
52 private:
53 std::atomic<short> current_{0};
54 std::atomic_flag write_lock_ ATOMIC_FLAG_INIT;
55 std::shared_ptr<T> ptrs_[2];
56};
57
58} // namespace utils
59
60USERVER_NAMESPACE_END