Shaka Player Embedded
ref_ptr.h
Go to the documentation of this file.
1 // Copyright 2016 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SHAKA_EMBEDDED_CORE_REF_PTR_H_
16 #define SHAKA_EMBEDDED_CORE_REF_PTR_H_
17 
18 #include <glog/logging.h>
19 
20 #include <iostream>
21 #include <string>
22 
23 #include "src/mapping/convert_js.h"
25 #include "src/mapping/names.h"
27 #include "src/util/templates.h"
28 
29 namespace shaka {
30 
31 template <typename T>
32 class Member;
33 
42 template <typename T>
43 class RefPtr {
44  static_assert(!util::is_v8_type<T>::value, "Cannot be used on V8 types.");
45 
46  public:
47  static std::string name() {
48  return TypeName<T>::name();
49  }
50 
51  RefPtr() {}
52 
53  RefPtr(std::nullptr_t) {} // NOLINT(runtime/explicit)
54 
55  template <typename U>
56  RefPtr(U* other) { // NOLINT(runtime/explicit)
57  reset(other);
58  }
59 
60  // Copy-constructors cannot have a template, even if it can be deduced.
61  RefPtr(const RefPtr& other) {
62  reset(other.ptr_);
63  }
64 
65  template <typename U>
66  RefPtr(const RefPtr<U>& other) {
67  reset(other.ptr_);
68  }
69 
70  // Move-constructors cannot have a template, even if it can be deduced.
71  RefPtr(RefPtr&& other) {
72  reset(other.ptr_);
73  other.reset();
74  }
75 
76  template <typename U>
77  RefPtr(RefPtr<U>&& other) {
78  reset(other.ptr_);
79  other.reset();
80  }
81 
82  ~RefPtr() {
83  reset();
84  }
85 
86  // Defined in member.h to avoid circular dependencies in the headers.
87  template <typename U>
88  RefPtr(const Member<U>& other); // NOLINT(runtime/explicit)
89  template <typename U>
90  RefPtr(Member<U>&& other); // NOLINT(runtime/explicit)
91 
92 
93  // Note this still supports other kinds of assignment because the constructors
94  // are not explicit. So when trying to assign a U*, it will first call
95  // the constructor, then the move constructor. This is less efficient, but
96  // avoids a lot of code duplication.
97  RefPtr& operator=(const RefPtr& other) {
98  reset(other.ptr_);
99  return *this;
100  }
101  RefPtr& operator=(RefPtr&& other) {
102  reset(other.ptr_);
103  other.reset();
104  return *this;
105  }
106 
107  T& operator*() const {
108  CHECK(ptr_);
109  return *ptr_;
110  }
111  T* operator->() const {
112  CHECK(ptr_);
113  return ptr_;
114  }
115  operator T*() const {
116  return ptr_;
117  }
118 
120  bool empty() const {
121  return ptr_ == nullptr;
122  }
123 
125  T* get() const {
126  return ptr_;
127  }
128 
129  template <typename U = T>
130  void reset(U* other = nullptr) {
131  // Add to other first in case other == ptr_, we don't want the GC to collect
132  // the object in between the calls.
133  static_assert(std::is_convertible<U*, T*>::value,
134  "U must be implicitly convertible to T");
135  memory::ObjectTracker::Instance()->AddRef(other);
136  memory::ObjectTracker::Instance()->RemoveRef(ptr_);
137  ptr_ = other;
138  }
139 
140  private:
141  template <typename U>
142  friend class RefPtr;
143 
144  T* ptr_ = nullptr;
145 };
146 
147 template <typename T>
148 std::ostream& operator<<(std::ostream& os, RefPtr<T> arg) {
149  if (arg.empty())
150  return os << "(NULL)";
151  else
152  return os << arg.get();
153 }
154 
155 template <typename T>
157  static bool FromJsValue(Handle<JsValue> source, RefPtr<T>* dest) {
158  if (IsNullOrUndefined(source)) {
159  dest->reset();
160  return true;
161  }
162 
163  // Get backing pointer and verify the type of the backing is correct.
164  BackingObject* ptr = GetInternalPointer(source);
165  if (!IsDerivedFrom(ptr, TypeName<T>::name()))
166  return false;
167 
168  dest->reset(static_cast<T*>(ptr));
169  return true;
170  }
171 
172  static ReturnVal<JsValue> ToJsValue(RefPtr<T> source) {
173  if (source.empty())
174  return JsNull();
175  else
176  return source->JsThis();
177  }
178 };
179 
180 } // namespace shaka
181 
182 #endif // SHAKA_EMBEDDED_CORE_REF_PTR_H_
RefPtr & operator=(const RefPtr &other)
Definition: ref_ptr.h:97
RefPtr(std::nullptr_t)
Definition: ref_ptr.h:53
const char * dest
Definition: media_utils.cc:31
static bool FromJsValue(Handle< JsValue > source, RefPtr< T > *dest)
Definition: ref_ptr.h:157
bool IsNullOrUndefined(Handle< JsValue > value)
Definition: js_wrappers.cc:311
ReturnVal< JsValue > JsNull()
Definition: js_wrappers.cc:288
BackingObject * GetInternalPointer(Handle< JsValue > value)
Definition: js_wrappers.cc:223
bool IsDerivedFrom(BackingObject *ptr, const std::string &name)
Definition: js_wrappers.cc:235
const char * source
Definition: media_utils.cc:30
T & operator*() const
Definition: ref_ptr.h:107
RefPtr(const RefPtr &other)
Definition: ref_ptr.h:61
bool empty() const
Definition: ref_ptr.h:120
RefPtr(RefPtr &&other)
Definition: ref_ptr.h:71
RefPtr(U *other)
Definition: ref_ptr.h:56
void reset(U *other=nullptr)
Definition: member.h:127
void reset(U *other=nullptr)
Definition: ref_ptr.h:130
static std::string name()
Definition: ref_ptr.h:47
RefPtr(const RefPtr< U > &other)
Definition: ref_ptr.h:66
RefPtr(RefPtr< U > &&other)
Definition: ref_ptr.h:77
static std::string name()
Definition: names.h:48
static ReturnVal< JsValue > ToJsValue(RefPtr< T > source)
Definition: ref_ptr.h:172
T * operator->() const
Definition: ref_ptr.h:111
RefPtr & operator=(RefPtr &&other)
Definition: ref_ptr.h:101