nlib
LimitedSharedPtr.h
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_THREADING_LIMITEDSHAREDPTR_H_
17 #define INCLUDE_NN_NLIB_THREADING_LIMITEDSHAREDPTR_H_
18 
19 #include <new>
20 #include <utility>
21 
22 #include "nn/nlib/Swap.h"
23 #include "nn/nlib/UniquePtr.h"
24 
25 NLIB_NAMESPACE_BEGIN
26 namespace threading {
27 
28 namespace internal {
29 
30 class LspStatus NLIB_FINAL {
31  public:
32  NLIB_CEXPR LspStatus() NLIB_NOEXCEPT : prv_(nullptr) {}
33  ~LspStatus() NLIB_NOEXCEPT {}
34  NLIB_DEFMOVE_PIMPL(LspStatus);
35  NLIB_DEPRECATED void swap(LspStatus& rhs) NLIB_NOEXCEPT { // NOLINT
36  using std::swap;
37  swap(prv_, rhs.prv_);
38  }
39  errno_t ToShare(LspStatus* ptr) NLIB_NOEXCEPT {
40  if (!prv_) {
41  prv_ = new (std::nothrow) int32_t(2);
42  if (!prv_) return ENOMEM;
43  } else {
45  }
46  NLIB_ASSERT(!ptr->prv_);
47  ptr->prv_ = prv_;
48  return 0;
49  }
50  bool ToUnshare() NLIB_NOEXCEPT {
51  if (!prv_) return false;
52  if (nlib_atomic_sub_fetch32(prv_, 1, NLIB_ATOMIC_ACQUIRE) == 0) {
53  delete prv_;
54  prv_ = nullptr;
55  return false;
56  }
57  prv_ = nullptr;
58  return true;
59  }
60  bool IsUnique() NLIB_NOEXCEPT {
61  if (!prv_) return true;
62  return nlib_atomic_load32(prv_, NLIB_ATOMIC_ACQUIRE) == 1;
63  }
64  void Reset() NLIB_NOEXCEPT { ToUnshare(); }
65 
66  private:
67  int32_t* prv_;
69 };
70 
71 } // namespace internal
72 
73 // Use of shared_ptr is discouraged because of unexpected overhead,
74 // and You have to share the pointer by calling MakeSharedFrom() method.
75 template <class T, class DEL = DefaultDelete<T> >
76 class LimitedSharedPtr {
77  public:
78  NLIB_CEXPR LimitedSharedPtr() NLIB_NOEXCEPT : ptr_(nullptr) {}
79  ~LimitedSharedPtr() NLIB_NOEXCEPT { release(); }
80  explicit LimitedSharedPtr(nullptr_t) NLIB_NOEXCEPT : ptr_(nullptr) {}
81  explicit LimitedSharedPtr(T* p) NLIB_NOEXCEPT : ptr_(p) {
82  // Do not count up LspStatus because there is the risk of alloc failure.
83  }
84 #ifdef __cpp_rvalue_references
85  LimitedSharedPtr(LimitedSharedPtr&& rhs) NLIB_NOEXCEPT
86  : ptr_(rhs.ptr_), status_(std::move(rhs.status_)) {
87  rhs.ptr_ = nullptr;
88  }
89  LimitedSharedPtr& operator=(LimitedSharedPtr&& rhs) NLIB_NOEXCEPT {
90  if (!status_.ToUnshare()) DEL()(ptr_);
91  ptr_ = rhs.ptr_;
92  rhs.ptr_ = nullptr;
93  status_ = std::move(rhs.status_);
94  return *this;
95  }
96 #endif
97  LimitedSharedPtr(LimitedSharedPtr& rhs, move_tag) NLIB_NOEXCEPT // NOLINT
98  : ptr_(rhs.ptr_), status_(rhs.status_, move_tag()) {
99  rhs.ptr_ = nullptr;
100  }
101  LimitedSharedPtr& assign(LimitedSharedPtr& rhs, move_tag) NLIB_NOEXCEPT { // NOLINT
102  if (!status_.ToUnshare()) DEL()(ptr_);
103  ptr_ = rhs.ptr_;
104  rhs.ptr_ = nullptr;
105  status_.assign(rhs.status_, move_tag());
106  return *this;
107  }
108  NLIB_DEPRECATED void swap(LimitedSharedPtr& rhs) NLIB_NOEXCEPT { // NOLINT
109  using std::swap;
110  swap(ptr_, rhs.ptr_);
111  swap(status_, rhs.status_);
112  }
113  void reset(T* p = 0) NLIB_NOEXCEPT {
114  if (!status_.ToUnshare()) DEL()(ptr_);
115  ptr_ = p;
116  }
117  T& operator*() const {
118  NLIB_ASSERT(ptr_ != nullptr);
119  return *ptr_;
120  }
121  T* operator->() const NLIB_NOEXCEPT {
122  NLIB_ASSERT(ptr_ != nullptr);
123  return ptr_;
124  }
125  T* get() const NLIB_NOEXCEPT { return ptr_; }
126  errno_t MakeSharedFrom(const LimitedSharedPtr& p) NLIB_NOEXCEPT; // NOLINT
127  bool IsUnique() const NLIB_NOEXCEPT { return status_.IsUnique(); }
128  bool MakeUniquePtr(UniquePtr<T>& p) NLIB_NOEXCEPT; // NOLINT
129  LimitedSharedPtr& operator=(nullptr_t) NLIB_NOEXCEPT {
130  release();
131  return *this;
132  }
133  NLIB_SAFE_BOOL(LimitedSharedPtr, ptr_ != nullptr);
134 
135  private:
136  void release() NLIB_NOEXCEPT {
137  if (!status_.ToUnshare()) DEL()(ptr_);
138  ptr_ = nullptr;
139  }
140 
141  private:
142  T* ptr_;
143  mutable internal::LspStatus status_;
144  NLIB_DISALLOW_COPY_AND_ASSIGN(LimitedSharedPtr);
145 };
146 
147 template <class T, class DEL>
148 errno_t LimitedSharedPtr<T, DEL>::MakeSharedFrom(const LimitedSharedPtr& p)
149  NLIB_NOEXCEPT { // NOLINT
150  LimitedSharedPtr tmp;
151  if (p) {
152  errno_t e = p.status_.ToShare(&tmp.status_);
153  if (e != 0) return e;
154  tmp.ptr_ = p.ptr_;
155  }
156  this->assign(tmp, move_tag());
157  return 0;
158 }
159 
160 template <class T, class DEL>
161 bool LimitedSharedPtr<T, DEL>::MakeUniquePtr(UniquePtr<T>& p) NLIB_NOEXCEPT { // NOLINT
162  if (IsUnique()) {
163  p.reset(ptr_);
164  ptr_ = nullptr;
165  release();
166  return true;
167  } else {
168  return false;
169  }
170 }
171 
172 template <class T, class DEL>
173 class LimitedSharedPtr<T[], DEL> {
174  private:
175  NLIB_DISALLOW_COPY_AND_ASSIGN(LimitedSharedPtr);
176 }; // not allowed for now
177 
178 } // namespace threading
179 NLIB_NAMESPACE_END
180 
181 NLIB_DEFINE_STD_SWAP_T_BEGIN3(nn, nlib, threading) // NOLINT
182 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::threading::LimitedSharedPtr) // NOLINT
183 NLIB_DEFINE_STD_SWAP_T_END3(nn, nlib, threading) // NOLINT
184 
185 #endif // INCLUDE_NN_NLIB_THREADING_LIMITEDSHAREDPTR_H_
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:179
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:194
Definition: Base64.h:25
std::unique_ptrに相当するクラスが定義されています。
#define NLIB_DEPRECATED
関数等がdeprecatedになったことを示します。
Definition: Config.h:109
#define NLIB_ATOMIC_ACQUIRE
gccの__ATOMIC_ACQUIREやC++11のstd::memory_order_acquireに準じます。
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()に準じます。
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:105
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:107
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
rhs を i 倍します。
Definition: DateTime.h:210
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:245
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37