1 // Copyright 2016 Google Inc. All rights reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef ZCPOINTER_ZCPOINTER_H_
16 #define ZCPOINTER_ZCPOINTER_H_
20 #include <forward_list>
26 class UseAfterFreeError
: public std
::logic_error
{
28 using std
::logic_error
::logic_error
;
31 #if defined(ZCPOINTER_TRACK_REFS) && ZCPOINTER_TRACK_REFS
33 template <typename T
> class ref
;
37 enum class OwnershipBehavior
{
43 class OwnedPtrDeleter
{
47 finalizer_(&OwnedPtrDeleter
<T
>::HandleDeletePointer
) {}
51 explicit OwnedPtrDeleter(OwnershipBehavior behavior
)
53 finalizer_(behavior
== OwnershipBehavior
::BORROW_POINTER
54 ?
&OwnedPtrDeleter
<T
>::HandleBorrowPointer
55 : &OwnedPtrDeleter
<T
>::HandleDeletePointer
) {
58 OwnedPtrDeleter(OwnedPtrDeleter
&& other
)
59 : refs_(std
::move(other
.refs_
)),
60 finalizer_(other
.finalizer_
) {
63 void operator=(const OwnedPtrDeleter
& o
) {
65 finalizer_
= o
.finalizer_
;
68 void operator()(T
* t
) const {
69 for (auto& ref
: refs_
) {
72 (this->finalizer_
)(t
);
78 void AddRef(ref
<T
>* ref
) {
79 refs_
.push_front(ref
);
82 void RemoveRef(ref
<T
>* ref
) {
86 static void HandleDeletePointer(T
* t
) {
90 static void HandleBorrowPointer(T
* t
) {}
93 void (*finalizer_
)(T
*);
94 std
::forward_list
<ref
<T
>*> refs_
;
97 void RaiseUseAfterFree() __attribute__((noreturn
));
99 } // namespace internal
101 template <typename T
>
102 class owned
: public std
::unique_ptr
<T
, internal
::OwnedPtrDeleter
<T
>> {
104 using Deleter
= internal
::OwnedPtrDeleter
<T
>;
107 using std
::unique_ptr
<T
, Deleter
>::unique_ptr
;
110 return ref
<T
>(*this);
115 return this->std
::unique_ptr
<T
, Deleter
>::get();
119 template <typename T
>
122 ref() : ptr_(nullptr) {}
124 ref(std
::nullptr_t
) : ref() {}
126 explicit ref(owned
<T
>& o
) : ptr_(nullptr) {
129 ptr_
->get_deleter().AddRef(this);
133 ref(const ref
<T
>& r
) {
137 ref
<T
>& operator=(const ref
<T
>& o
) {
139 if (ptr_
!= nullptr && !IsDeleted()) {
140 ptr_
->get_deleter().AddRef(this);
146 if (ptr_
!= nullptr && !IsDeleted()) {
147 ptr_
->get_deleter().RemoveRef(this);
152 T
* operator->() const {
154 return ptr_
->operator->();
157 bool operator==(const ref
<T
>& r
) const {
158 if (ptr_
== nullptr) {
159 return r
.ptr_
== nullptr;
161 return ptr_
== r
.ptr_
&& *ptr_
== *r
.ptr_
;
165 bool operator==(std
::nullptr_t
) const {
166 return ptr_
== nullptr;
169 bool operator!=(const ref
<T
>& r
) const {
170 return !(*this == r
);
174 friend class internal
::OwnedPtrDeleter
<T
>;
177 ptr_
= DeletedSentinel();
181 void CheckDeleted() const {
183 internal
::RaiseUseAfterFree();
187 bool IsDeleted() const {
188 return ptr_
== DeletedSentinel();
191 inline static owned
<T
>* DeletedSentinel() {
192 return reinterpret_cast<owned
<T
>*>(std
::numeric_limits
<uintptr_t>::max());
198 template <typename T
>
199 class member
: public T
{
208 owned
<T
> ptr_
= owned
<T
>(this,
209 internal
::OwnedPtrDeleter
<T
>(
210 internal
::OwnershipBehavior
::BORROW_POINTER
));
215 template <typename T
>
216 using owned
= std
::unique_ptr
<T
>;
218 template <typename T
>
221 template <typename T
>
228 #endif // ZCPOINTER_ZCPOINTER_H_