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 
21 #include "nn/nlib/Swap.h"
22 #include "nn/nlib/UniquePtr.h"
23 
24 NLIB_NAMESPACE_BEGIN
25 namespace threading {
26 
27 namespace internal {
28 
29 class LspStatus {
30  public:
31  NLIB_CEXPR LspStatus() NLIB_NOEXCEPT : value_(NULL) {}
32  ~LspStatus() NLIB_NOEXCEPT {}
33  NLIB_MOVE_MEMBER_HELPER_1(LspStatus, value_)
34  errno_t ToShare(LspStatus* ptr) NLIB_NOEXCEPT {
35  if (!value_) {
36  value_ = new (std::nothrow) int32_t(2);
37  if (!value_) return ENOMEM;
38  } else {
40  }
41  NLIB_ASSERT(!ptr->value_);
42  ptr->value_ = value_;
43  return 0;
44  }
45  bool ToUnshare() NLIB_NOEXCEPT {
46  if (!value_) return false;
47  if (nlib_atomic_sub_fetch32(value_, 1, NLIB_ATOMIC_ACQUIRE) == 0) {
48  delete value_;
49  value_ = NULL;
50  return false;
51  }
52  value_ = NULL;
53  return true;
54  }
55  bool IsUnique() NLIB_NOEXCEPT {
56  if (!value_) return true;
57  return nlib_atomic_load32(value_, NLIB_ATOMIC_ACQUIRE) == 1;
58  }
59  void swap(LspStatus& rhs) NLIB_NOEXCEPT { // NOLINT
60  using std::swap;
61  swap(value_, rhs.value_);
62  }
63 
64  private:
65  int32_t* value_;
67 };
68 
69 } // namespace internal
70 
71 // Use of shared_ptr is discouraged because of unexpected overhead,
72 // and You have to share the pointer by calling MakeSharedFrom() method.
73 template <class T, class DEL = DefaultDelete<T> >
74 class LimitedSharedPtr {
75  public:
76  LimitedSharedPtr() NLIB_NOEXCEPT : ptr_(NULL) {}
77  ~LimitedSharedPtr() NLIB_NOEXCEPT { release(); }
78  explicit LimitedSharedPtr(nullptr_t) NLIB_NOEXCEPT : ptr_(NULL) {}
79  explicit LimitedSharedPtr(T* p) NLIB_NOEXCEPT : ptr_(p) {
80  // Do not count up LspStatus because there is the risk of alloc failure.
81  }
82  NLIB_MOVE_MEMBER_HELPER_2(LimitedSharedPtr, ptr_, status_)
83  void reset(T* p = 0) NLIB_NOEXCEPT { LimitedSharedPtr<T>(p).swap(*this); }
84  T& operator*() const {
85  NLIB_ASSERT(ptr_ != NULL);
86  return *ptr_;
87  }
88  T* operator->() const NLIB_NOEXCEPT {
89  NLIB_ASSERT(ptr_ != NULL);
90  return ptr_;
91  }
92  T* get() const NLIB_NOEXCEPT { return ptr_; }
93  errno_t MakeSharedFrom(const LimitedSharedPtr& p) NLIB_NOEXCEPT; // NOLINT
94  bool IsUnique() const NLIB_NOEXCEPT { return status_.IsUnique(); }
95  bool MakeUniquePtr(UniquePtr<T>& p) NLIB_NOEXCEPT; // NOLINT
96  void swap(LimitedSharedPtr& rhs) NLIB_NOEXCEPT { // NOLINT
97  using std::swap;
98  swap(ptr_, rhs.ptr_);
99  status_.swap(rhs.status_);
100  }
101  LimitedSharedPtr& operator=(nullptr_t) NLIB_NOEXCEPT {
102  release();
103  return *this;
104  }
105  NLIB_SAFE_BOOL(LimitedSharedPtr, ptr_ != NULL);
106 
107  private:
108  void release() NLIB_NOEXCEPT {
109  if (!status_.ToUnshare()) DEL()(ptr_);
110  ptr_ = NULL;
111  }
112 
113  private:
114  T* ptr_;
115  mutable internal::LspStatus status_;
116  // NLIB_DISALLOW_COPY_AND_ASSIGN(LimitedSharedPtr);
117 };
118 
119 template <class T, class DEL>
120 errno_t LimitedSharedPtr<T, DEL>::MakeSharedFrom(const LimitedSharedPtr& p)
121  NLIB_NOEXCEPT { // NOLINT
122  LimitedSharedPtr tmp;
123  if (p) {
124  errno_t e = p.status_.ToShare(&tmp.status_);
125  if (e != 0) return e;
126  tmp.ptr_ = p.ptr_;
127  }
128  tmp.swap(*this);
129  return 0;
130 }
131 
132 template <class T, class DEL>
133 bool LimitedSharedPtr<T, DEL>::MakeUniquePtr(UniquePtr<T>& p) NLIB_NOEXCEPT { // NOLINT
134  if (IsUnique()) {
135  p.reset(ptr_);
136  ptr_ = NULL;
137  release();
138  return true;
139  } else {
140  return false;
141  }
142 }
143 
144 template <class T, class DEL>
145 class LimitedSharedPtr<T[], DEL> {
146  private:
147  NLIB_DISALLOW_COPY_AND_ASSIGN(LimitedSharedPtr);
148 }; // not allowed for now
149 
150 } // namespace threading
151 NLIB_NAMESPACE_END
152 
153 #ifndef NLIB_STD_SWAP_WORKAROUND
154 NLIB_NAMESPACE_BEGIN
155 #endif
156 
157 NLIB_DEFINE_STD_SWAP_T_BEGIN1(threading) // NOLINT
158 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::threading::LimitedSharedPtr) // NOLINT
159 NLIB_DEFINE_STD_SWAP_T_END1(threading) // NOLINT
160 
161 #ifndef NLIB_STD_SWAP_WORKAROUND
162 NLIB_NAMESPACE_END
163 #endif
164 
165 #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:163
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:178
std::unique_ptrに相当するクラスが定義されています。
#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:99
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:93
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
rhs を i 倍します。
Definition: DateTime.h:225
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37