• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_REF_COUNTED_H_
18 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_REF_COUNTED_H_
19 
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include <memory>
24 
25 #include "perfetto/base/logging.h"
26 
27 // A non-thread-safe refcounted implementation.
28 // Unlike std::shared_ptr The target class needs to explicitly derive
29 // RefCounted.
30 
31 // Usage:
32 // class MyRefcountedThing : public RefCounted {};
33 // ...
34 // RefPtr<MyRefcountedThing> shareable_ptr(new MyRefcountedThing());
35 // auto copy = shareable_ptr;
36 
37 namespace perfetto {
38 namespace trace_processor {
39 
40 // The base class that refcounted classes should inherit.
41 class RefCounted {
42  public:
43   RefCounted() = default;
44   RefCounted(RefCounted&&) noexcept = default;
45   RefCounted& operator=(RefCounted&&) noexcept = default;
46   RefCounted(const RefCounted&) = delete;
47   RefCounted& operator=(const RefCounted&) = delete;
48 
49  private:
50   template <typename T>
51   friend class RefPtr;
52 
AddRef()53   void AddRef() const {
54     PERFETTO_DCHECK(refcount_ >= 0);
55     ++refcount_;
56   }
Release()57   bool Release() const {
58     PERFETTO_DCHECK(refcount_ > 0);
59     return --refcount_ == 0;
60   }
61 
62   mutable intptr_t refcount_ = 0;
63 };
64 
65 // The RAII smart-pointer.
66 template <typename T>
67 class RefPtr {
68  public:
69   static_assert(std::is_base_of<RefCounted, T>::value,
70                 "T must be a descendant of RefCounted");
71 
72   // Adopt a newly created object.
RefPtr()73   RefPtr() : ptr_(nullptr) {}
RefPtr(T * ptr)74   explicit RefPtr(T* ptr) : ptr_(ptr) {
75     if (ptr_)
76       ptr_->AddRef();
77   }
78 
~RefPtr()79   ~RefPtr() { reset(); }
80 
reset()81   void reset() {
82     auto* old_ptr = ptr_;
83     ptr_ = nullptr;
84     if (old_ptr && old_ptr->Release())
85       delete old_ptr;
86   }
87 
88   // This case is really the move-assignment operator=(&&).
reset(T * new_obj)89   void reset(T* new_obj) { *this = RefPtr<T>(new_obj); }
90 
91   // Move operators.
RefPtr(RefPtr && move_from)92   RefPtr(RefPtr&& move_from) noexcept {
93     ptr_ = move_from.ptr_;
94     move_from.ptr_ = nullptr;
95   }
96 
97   RefPtr& operator=(RefPtr&& move_from) noexcept {
98     this->~RefPtr();
99     new (this) RefPtr(std::move(move_from));
100     return *this;
101   }
102 
103   // Copy operators.
RefPtr(const RefPtr & copy_from)104   RefPtr(const RefPtr& copy_from) {
105     ptr_ = copy_from.ptr_;
106     if (ptr_)
107       ptr_->AddRef();
108   }
109 
110   RefPtr& operator=(const RefPtr& copy_from) {
111     if (this != &copy_from) {
112       this->~RefPtr();
113       new (this) RefPtr(copy_from);
114     }
115     return *this;
116   }
117 
118   template <typename U>
119   bool operator==(const RefPtr<U>& rhs) const {
120     return ptr_ == rhs.ptr_;
121   }
122 
get()123   T* get() const { return ptr_; }
124   T* operator->() const { return ptr_; }
125   T& operator*() const { return *ptr_; }
126   explicit operator bool() const { return ptr_ != nullptr; }
127 
128  private:
129   T* ptr_ = nullptr;
130 };
131 
132 }  // namespace trace_processor
133 }  // namespace perfetto
134 
135 #endif  // INCLUDE_PERFETTO_TRACE_PROCESSOR_REF_COUNTED_H_
136