Plugin Power Saver: Fix a nullptr crash with plugin placeholder resize.
[chromium-blink-merge.git] / skia / ext / refptr.h
bloba7ba7ffb78542a7ec64e90dae696d0dfcd2e08fc
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_
8 #include <algorithm>
10 #include "base/move.h"
11 #include "third_party/skia/include/core/SkRefCnt.h"
13 namespace skia {
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;
28 // }
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());
35 // }
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
44 // count):
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
52 // for you.
53 template<typename T>
54 class RefPtr {
55 TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(RefPtr)
56 public:
57 RefPtr() : ptr_(nullptr) {}
59 RefPtr(decltype(nullptr)) : ptr_(nullptr) {}
61 RefPtr(const RefPtr& other)
62 : ptr_(other.get()) {
63 SkSafeRef(ptr_);
66 template<typename U>
67 RefPtr(const RefPtr<U>& other)
68 : ptr_(other.get()) {
69 SkSafeRef(ptr_);
72 template <typename U>
73 RefPtr(RefPtr<U>&& other)
74 : ptr_(other.get()) {
75 other.ptr_ = nullptr;
78 ~RefPtr() {
79 clear();
82 RefPtr& operator=(decltype(nullptr)) {
83 clear();
84 return *this;
87 RefPtr& operator=(const RefPtr& other) {
88 SkRefCnt_SafeAssign(ptr_, other.get());
89 return *this;
92 template<typename U>
93 RefPtr& operator=(const RefPtr<U>& other) {
94 SkRefCnt_SafeAssign(ptr_, other.get());
95 return *this;
98 template <typename U>
99 RefPtr& operator=(RefPtr<U>&& other) {
100 RefPtr<T> temp(other.Pass());
101 std::swap(ptr_, temp.ptr_);
102 return *this;
105 void clear() {
106 T* to_unref = ptr_;
107 ptr_ = nullptr;
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;
120 private:
121 T* ptr_;
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) {}
130 template<typename U>
131 friend RefPtr<U> AdoptRef(U* ptr);
133 template<typename U>
134 friend RefPtr<U> SharePtr(U* ptr);
136 template <typename U>
137 friend class RefPtr;
140 // For objects that have an unowned reference (such as newly created objects).
141 template<typename T>
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.
146 template<typename T>
147 RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); }
149 } // namespace skia
151 #endif // SKIA_EXT_REFPTR_H_