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 10namespace 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. 44template<typename T> 45class RefPtr { 46 public: 47 RefPtr() : ptr_(NULL) {} 48 49 RefPtr(const RefPtr& other) 50 : ptr_(other.get()) { 51 SkSafeRef(ptr_); 52 } 53 54 template<typename U> 55 RefPtr(const RefPtr<U>& other) 56 : ptr_(other.get()) { 57 SkSafeRef(ptr_); 58 } 59 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 75 void clear() { 76 T* to_unref = ptr_; 77 ptr_ = NULL; 78 SkSafeUnref(to_unref); 79 } 80 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; 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). 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). 108template<typename T> 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. 113template<typename T> 114RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); } 115 116} // namespace skia 117 118#endif // SKIA_EXT_REFPTR_H_ 119