Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarAtomicSharedPtr.hpp
blob: 3ca909b7b7fe0dd2cf6047b16cb47b9e7eed4623 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#pragma once

#include "StarThread.hpp"

namespace Star {

// Thread safe shared_ptr such that is is possible to safely access the
// contents of the shared_ptr while other threads might be updating it.  Makes
// it possible to safely do Read Copy Update.
template <typename T>
class AtomicSharedPtr {
public:
  typedef shared_ptr<T> SharedPtr;
  typedef weak_ptr<T> WeakPtr;

  AtomicSharedPtr();
  AtomicSharedPtr(AtomicSharedPtr const& p);
  AtomicSharedPtr(AtomicSharedPtr&& p);
  AtomicSharedPtr(SharedPtr p);

  SharedPtr load() const;
  WeakPtr weak() const;
  void store(SharedPtr p);
  void reset();

  explicit operator bool() const;
  bool unique() const;

  SharedPtr operator->() const;

  AtomicSharedPtr& operator=(AtomicSharedPtr const& p);
  AtomicSharedPtr& operator=(AtomicSharedPtr&& p);
  AtomicSharedPtr& operator=(SharedPtr p);

private:
  SharedPtr m_ptr;
  mutable SpinLock m_lock;
};

template <typename T>
AtomicSharedPtr<T>::AtomicSharedPtr() {}

template <typename T>
AtomicSharedPtr<T>::AtomicSharedPtr(AtomicSharedPtr const& p)
  : m_ptr(p.load()) {}

template <typename T>
AtomicSharedPtr<T>::AtomicSharedPtr(AtomicSharedPtr&& p)
  : m_ptr(std::move(p.m_ptr)) {}

template <typename T>
AtomicSharedPtr<T>::AtomicSharedPtr(SharedPtr p)
  : m_ptr(std::move(p)) {}

template <typename T>
auto AtomicSharedPtr<T>::load() const -> SharedPtr {
  SpinLocker locker(m_lock);
  return m_ptr;
}

template <typename T>
auto AtomicSharedPtr<T>::weak() const -> WeakPtr {
  SpinLocker locker(m_lock);
  return WeakPtr(m_ptr);
}

template <typename T>
void AtomicSharedPtr<T>::store(SharedPtr p) {
  SpinLocker locker(m_lock);
  m_ptr = std::move(p);
}

template <typename T>
void AtomicSharedPtr<T>::reset() {
  SpinLocker locker(m_lock);
  m_ptr.reset();
}

template <typename T>
AtomicSharedPtr<T>::operator bool() const {
  SpinLocker locker(m_lock);
  return (bool)m_ptr;
}

template <typename T>
bool AtomicSharedPtr<T>::unique() const {
  SpinLocker locker(m_lock);
  return m_ptr.unique();
}

template <typename T>
auto AtomicSharedPtr<T>::operator-> () const -> SharedPtr {
  SpinLocker locker(m_lock);
  return m_ptr;
}

template <typename T>
AtomicSharedPtr<T>& AtomicSharedPtr<T>::operator=(AtomicSharedPtr const& p) {
  SpinLocker locker(m_lock);
  m_ptr = p.load();
  return *this;
}

template <typename T>
AtomicSharedPtr<T>& AtomicSharedPtr<T>::operator=(AtomicSharedPtr&& p) {
  SpinLocker locker(m_lock);
  m_ptr = std::move(p.m_ptr);
  return *this;
}

template <typename T>
AtomicSharedPtr<T>& AtomicSharedPtr<T>::operator=(SharedPtr p) {
  SpinLocker locker(m_lock);
  m_ptr = std::move(p);
  return *this;
}

}