1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef SKIA_EXT_REFPTR_H_
6 #define SKIA_EXT_REFPTR_H_
10 #include "base/move.h"
11 #include "third_party/skia/include/core/SkRefCnt.h"
15 // When creating/receiving a ref-counted pointer from Skia, wrap that pointer in
16 // this class to avoid dealing with the ref-counting and prevent leaks/crashes
17 // due to ref-counting bugs.
19 // Example of creating a new SkShader* and setting it on a SkPaint:
20 // skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::Create());
21 // paint.setShader(shader.get());
23 // When passing around a ref-counted pointer to methods outside of Skia, always
24 // pass around the skia::RefPtr instead of the raw pointer. An example method
25 // that takes a SkShader* parameter and saves the SkShader* in the class.
26 // void AMethodThatSavesAShader(const skia::RefPtr<SkShader>& shader) {
27 // member_refptr_ = shader;
29 // skia::RefPtr<SkShader> member_refptr_;
31 // When returning a ref-counted pointer, also return the skia::RefPtr instead.
32 // An example method that creates an SkShader* and returns it:
33 // skia::RefPtr<SkShader> MakeAShader() {
34 // return skia::AdoptRef(SkGradientShader::Create());
37 // To take a scoped reference to an object whose references are all owned
38 // by other objects (i.e. does not have one that needs to be adopted) use the
39 // skia::SharePtr helper:
41 // skia::RefPtr<SkShader> shader = skia::SharePtr(paint.getShader());
43 // To pass a reference while clearing the pointer (without changing the ref
46 // skia::RefPtr<SkShader> shader = ...;
47 // UseThisShader(shader.Pass());
49 // Never call ref() or unref() on the underlying ref-counted pointer. If you
50 // AdoptRef() the raw pointer immediately into a skia::RefPtr and always work
51 // with skia::RefPtr instances instead, the ref-counting will be taken care of
55 TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(RefPtr
)
57 RefPtr() : ptr_(nullptr) {}
59 RefPtr(decltype(nullptr)) : ptr_(nullptr) {}
61 RefPtr(const RefPtr
& other
)
67 RefPtr(const RefPtr
<U
>& other
)
73 RefPtr(RefPtr
<U
>&& other
)
82 RefPtr
& operator=(decltype(nullptr)) {
87 RefPtr
& operator=(const RefPtr
& other
) {
88 SkRefCnt_SafeAssign(ptr_
, other
.get());
93 RefPtr
& operator=(const RefPtr
<U
>& other
) {
94 SkRefCnt_SafeAssign(ptr_
, other
.get());
99 RefPtr
& operator=(RefPtr
<U
>&& other
) {
100 RefPtr
<T
> temp(other
.Pass());
101 std::swap(ptr_
, temp
.ptr_
);
108 SkSafeUnref(to_unref
);
111 T
* get() const { return ptr_
; }
112 T
& operator*() const { return *ptr_
; }
113 T
* operator->() const { return ptr_
; }
115 typedef T
* RefPtr::*unspecified_bool_type
;
116 operator unspecified_bool_type() const {
117 return ptr_
? &RefPtr::ptr_
: nullptr;
123 // This function cannot be public because Skia starts its ref-counted
124 // objects at refcnt=1. This makes it impossible to differentiate
125 // between a newly created object (that doesn't need to be ref'd) or an
126 // already existing object with one owner (that does need to be ref'd so that
127 // this RefPtr can also manage its lifetime).
128 explicit RefPtr(T
* ptr
) : ptr_(ptr
) {}
131 friend RefPtr
<U
> AdoptRef(U
* ptr
);
134 friend RefPtr
<U
> SharePtr(U
* ptr
);
136 template <typename U
>
140 // For objects that have an unowned reference (such as newly created objects).
142 RefPtr
<T
> AdoptRef(T
* ptr
) { return RefPtr
<T
>(ptr
); }
144 // For objects that are already owned. This doesn't take ownership of existing
145 // references and adds a new one.
147 RefPtr
<T
> SharePtr(T
* ptr
) { return RefPtr
<T
>(SkSafeRef(ptr
)); }
151 #endif // SKIA_EXT_REFPTR_H_