• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)109 RefPtr<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)114 RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); }
115 
116 }  // namespace skia
117 
118 #endif  // SKIA_EXT_REFPTR_H_
119