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. 4 5 #ifndef SKIA_EXT_REFPTR_H_ 6 #define SKIA_EXT_REFPTR_H_ 7 8 #include "third_party/skia/include/core/SkRefCnt.h" 9 10 namespace skia { 11 12 // 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 // due to ref-counting bugs. 15 // 16 // Example of creating a new SkShader* and setting it on a SkPaint: 17 // skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::Create()); 18 // paint.setShader(shader.get()); 19 // 20 // When passing around a ref-counted pointer to methods outside of Skia, always 21 // pass around the skia::RefPtr instead of the raw pointer. An example method 22 // that takes a SkShader* parameter and saves the SkShader* in the class. 23 // void AMethodThatSavesAShader(const skia::RefPtr<SkShader>& shader) { 24 // member_refptr_ = shader; 25 // } 26 // skia::RefPtr<SkShader> member_refptr_; 27 // 28 // When returning a ref-counted pointer, also return the skia::RefPtr instead. 29 // An example method that creates an SkShader* and returns it: 30 // skia::RefPtr<SkShader> MakeAShader() { 31 // return skia::AdoptRef(SkGradientShader::Create()); 32 // } 33 // 34 // To take a scoped reference to an object whose references are all owned 35 // by other objects (i.e. does not have one that needs to be adopted) use the 36 // skia::SharePtr helper: 37 // 38 // skia::RefPtr<SkShader> shader = skia::SharePtr(paint.getShader()); 39 // 40 // 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 // with skia::RefPtr instances instead, the ref-counting will be taken care of 43 // for you. 44 template<typename T> 45 class RefPtr { 46 public: RefPtr()47 RefPtr() : ptr_(NULL) {} 48 RefPtr(const RefPtr & other)49 RefPtr(const RefPtr& other) 50 : ptr_(other.get()) { 51 SkSafeRef(ptr_); 52 } 53 54 template<typename U> RefPtr(const RefPtr<U> & other)55 RefPtr(const RefPtr<U>& other) 56 : ptr_(other.get()) { 57 SkSafeRef(ptr_); 58 } 59 ~RefPtr()60 ~RefPtr() { 61 clear(); 62 } 63 64 RefPtr& operator=(const RefPtr& other) { 65 SkRefCnt_SafeAssign(ptr_, other.get()); 66 return *this; 67 } 68 69 template<typename U> 70 RefPtr& operator=(const RefPtr<U>& other) { 71 SkRefCnt_SafeAssign(ptr_, other.get()); 72 return *this; 73 } 74 clear()75 void clear() { 76 T* to_unref = ptr_; 77 ptr_ = NULL; 78 SkSafeUnref(to_unref); 79 } 80 get()81 T* get() const { return ptr_; } 82 T& operator*() const { return *ptr_; } 83 T* operator->() const { return ptr_; } 84 85 typedef T* RefPtr::*unspecified_bool_type; unspecified_bool_type()86 operator unspecified_bool_type() const { 87 return ptr_ ? &RefPtr::ptr_ : NULL; 88 } 89 90 private: 91 T* ptr_; 92 93 // This function cannot be public because Skia starts its ref-counted 94 // 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 96 // already existing object with one owner (that does need to be ref'd so that 97 // this RefPtr can also manage its lifetime). RefPtr(T * ptr)98 explicit RefPtr(T* ptr) : ptr_(ptr) {} 99 100 template<typename U> 101 friend RefPtr<U> AdoptRef(U* ptr); 102 103 template<typename U> 104 friend RefPtr<U> SharePtr(U* ptr); 105 }; 106 107 // For objects that have an unowned reference (such as newly created objects). 108 template<typename T> AdoptRef(T * ptr)109RefPtr<T> AdoptRef(T* ptr) { return RefPtr<T>(ptr); } 110 111 // For objects that are already owned. This doesn't take ownership of existing 112 // references and adds a new one. 113 template<typename T> SharePtr(T * ptr)114RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); } 115 116 } // namespace skia 117 118 #endif // SKIA_EXT_REFPTR_H_ 119