Home | History | Annotate | Download | only in ext
      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:
     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).
    108 template<typename T>
    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>
    114 RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); }
    115 
    116 }  // namespace skia
    117 
    118 #endif  // SKIA_EXT_REFPTR_H_
    119