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)
Loads a value in an atomic operation. Its behavior is similar to the one for __atomic_load_n() of gcc...
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:163
#define NLIB_SAFE_BOOL(class_name, exp)
Defines a safe operator bool function in the class. Uses the C++11 explicit bool if it is available f...
Definition: Config.h:178
Defines that class that is corresponding to std::unique_ptr.
#define NLIB_ATOMIC_ACQUIRE
Similar to __ATOMIC_ACQUIRE of gcc or std::memory_order_acquire of C++11.
int32_t nlib_atomic_sub_fetch32(int32_t *ptr, int32_t val, int memorder)
Subtracts atomic values. Its behavior is similar to the one for __atomic_sub_fetch() of gcc...
int32_t nlib_atomic_add_fetch32(int32_t *ptr, int32_t val, int memorder)
Adds atomic values. Its behavior is similar to the one for __atomic_add_fetch() of gcc...
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:93
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
Increases rhs by a factor of i.
Definition: DateTime.h:225
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:37