nlib
LimitedSharedPtr.h
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_THREADING_LIMITEDSHAREDPTR_H_
4 #define INCLUDE_NN_NLIB_THREADING_LIMITEDSHAREDPTR_H_
5 
6 #include <new>
7 
8 #include "nn/nlib/Swap.h"
9 #include "nn/nlib/UniquePtr.h"
10 
11 NLIB_NAMESPACE_BEGIN
12 namespace threading {
13 
14 namespace internal {
15 
16 class LspStatus {
17  public:
18  NLIB_CEXPR LspStatus() NLIB_NOEXCEPT : m_V(NULL) {}
19  ~LspStatus() NLIB_NOEXCEPT {}
20  NLIB_MOVE_MEMBER_HELPER_1(LspStatus, m_V)
21  errno_t ToShare(LspStatus* ptr) NLIB_NOEXCEPT {
22  if (!m_V) {
23  m_V = new (std::nothrow) int32_t(2);
24  if (!m_V) return ENOMEM;
25  } else {
27  }
28  NLIB_ASSERT(!ptr->m_V);
29  ptr->m_V = m_V;
30  return 0;
31  }
32  bool ToUnshare() NLIB_NOEXCEPT {
33  if (!m_V) return false;
34  if (nlib_atomic_sub_fetch32(m_V, 1, NLIB_ATOMIC_ACQUIRE) == 0) {
35  delete m_V;
36  m_V = NULL;
37  return false;
38  }
39  m_V = NULL;
40  return true;
41  }
42  bool IsUnique() NLIB_NOEXCEPT {
43  if (!m_V) return true;
44  return nlib_atomic_load32(m_V, NLIB_ATOMIC_ACQUIRE) == 1;
45  }
46  void swap(LspStatus& rhs) NLIB_NOEXCEPT { // NOLINT
47  using std::swap;
48  swap(m_V, rhs.m_V);
49  }
50 
51  private:
52  int32_t* m_V;
54 };
55 
56 } // namespace internal
57 
58 // Use of shared_ptr is discouraged because of unexpected overhead,
59 // and You have to share the pointer by calling MakeSharedFrom() method.
60 template <class T, class DEL = DefaultDelete<T> >
61 class LimitedSharedPtr {
62  public:
63  LimitedSharedPtr() NLIB_NOEXCEPT : m_Ptr(NULL) {}
64  ~LimitedSharedPtr() NLIB_NOEXCEPT { release(); }
65  explicit LimitedSharedPtr(nullptr_t) NLIB_NOEXCEPT : m_Ptr(NULL) {}
66  explicit LimitedSharedPtr(T* p) NLIB_NOEXCEPT : m_Ptr(p) {
67  // Do not count up LspStatus because there is the risk of alloc failure.
68  }
69  NLIB_MOVE_MEMBER_HELPER_2(LimitedSharedPtr, m_Ptr, m_Status)
70  void reset(T* p = 0) NLIB_NOEXCEPT { LimitedSharedPtr<T>(p).swap(*this); }
71  T& operator*() const {
72  NLIB_ASSERT(m_Ptr != NULL);
73  return *m_Ptr;
74  }
75  T* operator->() const NLIB_NOEXCEPT {
76  NLIB_ASSERT(m_Ptr != NULL);
77  return m_Ptr;
78  }
79  T* get() const NLIB_NOEXCEPT { return m_Ptr; }
80  errno_t MakeSharedFrom(const LimitedSharedPtr& p) NLIB_NOEXCEPT; // NOLINT
81  bool IsUnique() const NLIB_NOEXCEPT { return m_Status.IsUnique(); }
82  bool MakeUniquePtr(UniquePtr<T>& p) NLIB_NOEXCEPT; // NOLINT
83  void swap(LimitedSharedPtr& rhs) NLIB_NOEXCEPT { // NOLINT
84  using std::swap;
85  swap(m_Ptr, rhs.m_Ptr);
86  m_Status.swap(rhs.m_Status);
87  }
88  LimitedSharedPtr& operator=(nullptr_t) NLIB_NOEXCEPT {
89  release();
90  return *this;
91  }
92  NLIB_SAFE_BOOL(LimitedSharedPtr, m_Ptr != NULL);
93 
94  private:
95  void release() NLIB_NOEXCEPT {
96  if (!m_Status.ToUnshare()) DEL()(m_Ptr);
97  m_Ptr = NULL;
98  }
99 
100  private:
101  T* m_Ptr;
102  mutable internal::LspStatus m_Status;
103  // NLIB_DISALLOW_COPY_AND_ASSIGN(LimitedSharedPtr);
104 };
105 
106 template <class T, class DEL>
107 errno_t LimitedSharedPtr<T, DEL>::MakeSharedFrom(const LimitedSharedPtr& p)
108  NLIB_NOEXCEPT { // NOLINT
109  LimitedSharedPtr tmp;
110  if (p) {
111  errno_t e = p.m_Status.ToShare(&tmp.m_Status);
112  if (e != 0) return e;
113  tmp.m_Ptr = p.m_Ptr;
114  }
115  tmp.swap(*this);
116  return 0;
117 }
118 
119 template <class T, class DEL>
120 bool LimitedSharedPtr<T, DEL>::MakeUniquePtr(UniquePtr<T>& p) NLIB_NOEXCEPT { // NOLINT
121  if (IsUnique()) {
122  p.reset(m_Ptr);
123  m_Ptr = NULL;
124  release();
125  return true;
126  } else {
127  return false;
128  }
129 }
130 
131 template <class T, class DEL>
132 class LimitedSharedPtr<T[], DEL> {
133  private:
134  NLIB_DISALLOW_COPY_AND_ASSIGN(LimitedSharedPtr);
135 }; // not allowed for now
136 
137 /*
138 template <class T1, class D1, class T2, class D2>
139 bool operator==(const LimitedSharedPtr<T1, D1>& rhs, const LimitedSharedPtr<T2, D2>& lhs) {
140  return rhs.get() == lhs.get();
141 }
142 
143 template <class T1, class D1>
144 bool operator==(const LimitedSharedPtr<T1, D1>& lhs, nullptr_t) {
145  return !lhs;
146 }
147 
148 template <class T1, class D1>
149 bool operator==(nullptr_t, const LimitedSharedPtr<T1, D1>& rhs) {
150  return !rhs;
151 }
152 
153 template <class T1, class D1, class T2, class D2>
154 bool operator!=(const LimitedSharedPtr<T1, D1>& rhs, const LimitedSharedPtr<T2, D2>& lhs) {
155  return rhs.get() != lhs.get();
156 }
157 
158 template <class T1, class D1>
159 bool operator!=(const LimitedSharedPtr<T1, D1>& lhs, nullptr_t) {
160  return static_cast<bool>(lhs);
161 }
162 
163 template <class T1, class D1>
164 bool operator!=(nullptr_t, const LimitedSharedPtr<T1, D1>& rhs) {
165  return static_cast<bool>(rhs);
166 }
167 */
168 
169 } // namespace threading
170 NLIB_NAMESPACE_END
171 
172 #ifndef NLIB_STD_SWAP_WORKAROUND
173 NLIB_NAMESPACE_BEGIN
174 #endif
175 
176 NLIB_DEFINE_STD_SWAP_T_BEGIN1(threading) // NOLINT
177 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::threading::LimitedSharedPtr) // NOLINT
178 NLIB_DEFINE_STD_SWAP_T_END1(threading) // NOLINT
179 
180 #ifndef NLIB_STD_SWAP_WORKAROUND
181 NLIB_NAMESPACE_END
182 #endif
183 
184 #endif // INCLUDE_NN_NLIB_THREADING_LIMITEDSHAREDPTR_H_
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Platform.h:2151
int32_t nlib_atomic_load32(const int32_t *ptr, int memorder)
アトミックに値をロードします。動作はgccの__atomic_load_n()に準じます。
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:126
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:141
std::unique_ptrに相当するクラスが定義されています。
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
int32_t nlib_atomic_sub_fetch32(int32_t *ptr, int32_t val, int memorder)
アトミックな値の減算を行います。動作はgccの__atomic_sub_fetch()に準じます。
int32_t nlib_atomic_add_fetch32(int32_t *ptr, int32_t val, int memorder)
アトミックな値の加算を行います。動作はgccの__atomic_add_fetch()に準じます。
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
rhs を i 倍します。
Definition: DateTime.h:213
#define NLIB_ATOMIC_ACQUIRE
gccの__ATOMIC_ACQUIREやC++11のstd::memory_order_acquireに準じます。
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:24