Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: skia/ext/refptr.h

Issue 19267024: cc: Don't leak a ref to SkColorFilter. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: filterleak: better Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/output/gl_renderer.cc ('k') | skia/ext/refptr_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef SKIA_EXT_REFPTR_H_ 5 #ifndef SKIA_EXT_REFPTR_H_
6 #define SKIA_EXT_REFPTR_H_ 6 #define SKIA_EXT_REFPTR_H_
7 7
8 #include "base/basictypes.h"
8 #include "third_party/skia/include/core/SkRefCnt.h" 9 #include "third_party/skia/include/core/SkRefCnt.h"
9 10
10 namespace skia { 11 namespace skia {
11 12
12 // When creating/receiving a ref-counted pointer from Skia, wrap that pointer in 13 // When creating/receiving a ref-counted pointer from Skia, wrap that pointer in
13 // this class to avoid dealing with the ref-counting and prevent leaks/crashes 14 // this class to avoid dealing with the ref-counting and prevent leaks/crashes
14 // due to ref-counting bugs. 15 // due to ref-counting bugs.
15 // 16 //
16 // Example of creating a new SkShader* and setting it on a SkPaint: 17 // Example of creating a new SkShader* and setting it on a SkPaint:
17 // skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::Create()); 18 // skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::Create());
(...skipping 19 matching lines...) Expand all
37 // 38 //
38 // skia::RefPtr<SkShader> shader = skia::SharePtr(paint.getShader()); 39 // skia::RefPtr<SkShader> shader = skia::SharePtr(paint.getShader());
39 // 40 //
40 // Never call ref() or unref() on the underlying ref-counted pointer. If you 41 // Never call ref() or unref() on the underlying ref-counted pointer. If you
41 // AdoptRef() the raw pointer immediately into a skia::RefPtr and always work 42 // AdoptRef() the raw pointer immediately into a skia::RefPtr and always work
42 // with skia::RefPtr instances instead, the ref-counting will be taken care of 43 // with skia::RefPtr instances instead, the ref-counting will be taken care of
43 // for you. 44 // for you.
44 template<typename T> 45 template<typename T>
45 class RefPtr { 46 class RefPtr {
46 public: 47 public:
47 RefPtr() : ptr_(NULL) {} 48 RefPtr() : ptr_(NULL) {
49 #ifndef NDEBUG
50 inside_receive_and_adopt_ref_ = false;
51 #endif
52 }
48 53
49 RefPtr(const RefPtr& other) 54 RefPtr(const RefPtr& other)
50 : ptr_(other.get()) { 55 : ptr_(other.get()) {
51 SkSafeRef(ptr_); 56 SkSafeRef(ptr_);
57 #ifndef NDEBUG
58 inside_receive_and_adopt_ref_ = false;
59 #endif
52 } 60 }
53 61
54 template<typename U> 62 template<typename U>
55 RefPtr(const RefPtr<U>& other) 63 RefPtr(const RefPtr<U>& other)
56 : ptr_(other.get()) { 64 : ptr_(other.get()) {
57 SkSafeRef(ptr_); 65 SkSafeRef(ptr_);
66 #ifndef NDEBUG
67 inside_receive_and_adopt_ref_ = false;
68 #endif
58 } 69 }
59 70
60 ~RefPtr() { 71 ~RefPtr() {
72 ShouldNotBeInsideReceiveAndAdoptRef();
61 clear(); 73 clear();
62 } 74 }
63 75
64 RefPtr& operator=(const RefPtr& other) { 76 RefPtr& operator=(const RefPtr& other) {
77 ShouldNotBeInsideReceiveAndAdoptRef();
65 SkRefCnt_SafeAssign(ptr_, other.get()); 78 SkRefCnt_SafeAssign(ptr_, other.get());
66 return *this; 79 return *this;
67 } 80 }
68 81
69 template<typename U> 82 template<typename U>
70 RefPtr& operator=(const RefPtr<U>& other) { 83 RefPtr& operator=(const RefPtr<U>& other) {
84 ShouldNotBeInsideReceiveAndAdoptRef();
71 SkRefCnt_SafeAssign(ptr_, other.get()); 85 SkRefCnt_SafeAssign(ptr_, other.get());
72 return *this; 86 return *this;
73 } 87 }
74 88
75 void clear() { 89 void clear() {
90 ShouldNotBeInsideReceiveAndAdoptRef();
76 T* to_unref = ptr_; 91 T* to_unref = ptr_;
77 ptr_ = NULL; 92 ptr_ = NULL;
78 SkSafeUnref(to_unref); 93 SkSafeUnref(to_unref);
79 } 94 }
80 95
81 T* get() const { return ptr_; } 96 T* get() const {
82 T& operator*() const { return *ptr_; } 97 ShouldNotBeInsideReceiveAndAdoptRef();
83 T* operator->() const { return ptr_; } 98 return ptr_;
99 }
100 T& operator*() const {
101 ShouldNotBeInsideReceiveAndAdoptRef();
102 return *ptr_;
103 }
104 T* operator->() const {
105 ShouldNotBeInsideReceiveAndAdoptRef();
106 return ptr_;
107 }
84 108
85 typedef T* RefPtr::*unspecified_bool_type; 109 typedef T* RefPtr::*unspecified_bool_type;
86 operator unspecified_bool_type() const { 110 operator unspecified_bool_type() const {
111 ShouldNotBeInsideReceiveAndAdoptRef();
87 return ptr_ ? &RefPtr::ptr_ : NULL; 112 return ptr_ ? &RefPtr::ptr_ : NULL;
88 } 113 }
89 114
115 class Receiver {
116 public:
117 ~Receiver() {
118 refptr_->ShouldBeEmpty();
119 refptr_->ptr_ = ptr_;
120 refptr_->inside_receive_and_adopt_ref_ = false;
121 }
122
123 operator T**() { return &ptr_; }
124
125 private:
126 friend class RefPtr;
127
128 explicit Receiver(RefPtr* refptr) : refptr_(refptr), ptr_(NULL) {
129 refptr_->ShouldBeEmpty();
130 }
131
132 RefPtr* refptr_;
133 T* ptr_;
134
135 DISALLOW_COPY_AND_ASSIGN(Receiver);
136 };
137
138 // Call this and pass the returned temporary it to a function taking a T**
139 // argument. The returned temporary will set the original RefPtr to an object
140 // with an unowned reference.
141 // NOTE: Do not use this function as part of a subexpression where the RefPtr
142 // is also used somewhere else. Destructors of temporaries are only run at the
143 // end of a full expression so the initialization will not be complete and
144 // the RefPtr will remain empty.
Stephen White 2013/07/18 15:50:30 Maybe I'm old-fashioned, but I'm wondering if this
danakj 2013/07/18 15:59:36 My own preference would be to never receive someth
awong 2013/07/18 16:00:42 Yes...I agree but there's precedent (bleck). See
145 //
146 // Bad (refptr will be NULL when it is dereffed):
147 // Foo(refptr.ReceiveAndAdoptRef()) && refptr->Bar();
148 // Good:
149 // bool ok = Foo(refptr.ReceiveAndAdoptRef());
150 // ok && refptr->Bar();
151 Receiver ReceiveAndAdoptRef() {
152 #ifndef NDEBUG
153 inside_receive_and_adopt_ref_ = true;
154 #endif
155 return Receiver(this);
156 }
157
90 private: 158 private:
91 T* ptr_; 159 T* ptr_;
92 160
161 #ifndef NDEBUG
162 bool inside_receive_and_adopt_ref_;
163 #endif
164
165 inline int ShouldNotBeInsideReceiveAndAdoptRef() const {
166 #ifndef NDEBUG
167 if (inside_receive_and_adopt_ref_) {
168 // Crash. Can't use DCHECK here because blink includes this file.
169 volatile int* a = NULL;
170 return *a;
171 }
172 #endif
173 return 0;
174 }
175
176 inline int ShouldBeEmpty() const {
177 #ifndef NDEBUG
178 if (ptr_ != NULL) {
179 // Crash. Can't use DCHECK here because blink includes this file.
180 volatile int* a = NULL;
181 return *a;
182 }
183 #endif
184 return 0;
185 }
186
93 // This function cannot be public because Skia starts its ref-counted 187 // This function cannot be public because Skia starts its ref-counted
94 // objects at refcnt=1. This makes it impossible to differentiate 188 // objects at refcnt=1. This makes it impossible to differentiate
95 // between a newly created object (that doesn't need to be ref'd) or an 189 // between a newly created object (that doesn't need to be ref'd) or an
96 // already existing object with one owner (that does need to be ref'd so that 190 // already existing object with one owner (that does need to be ref'd so that
97 // this RefPtr can also manage its lifetime). 191 // this RefPtr can also manage its lifetime).
98 explicit RefPtr(T* ptr) : ptr_(ptr) {} 192 explicit RefPtr(T* ptr) : ptr_(ptr) {
193 #ifndef NDEBUG
194 inside_receive_and_adopt_ref_ = false;
195 #endif
196 }
99 197
100 template<typename U> 198 template<typename U>
101 friend RefPtr<U> AdoptRef(U* ptr); 199 friend RefPtr<U> AdoptRef(U* ptr);
102 200
103 template<typename U> 201 template<typename U>
104 friend RefPtr<U> SharePtr(U* ptr); 202 friend RefPtr<U> SharePtr(U* ptr);
105 }; 203 };
106 204
107 // For objects that have an unowned reference (such as newly created objects). 205 // For objects that have an unowned reference (such as newly created objects).
108 template<typename T> 206 template<typename T>
109 RefPtr<T> AdoptRef(T* ptr) { return RefPtr<T>(ptr); } 207 RefPtr<T> AdoptRef(T* ptr) { return RefPtr<T>(ptr); }
110 208
111 // For objects that are already owned. This doesn't take ownership of existing 209 // For objects that are already owned. This doesn't take ownership of existing
112 // references and adds a new one. 210 // references and adds a new one.
113 template<typename T> 211 template<typename T>
114 RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); } 212 RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); }
115 213
116 } // namespace skia 214 } // namespace skia
117 215
118 #endif // SKIA_EXT_REFPTR_H_ 216 #endif // SKIA_EXT_REFPTR_H_
OLDNEW
« no previous file with comments | « cc/output/gl_renderer.cc ('k') | skia/ext/refptr_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698