Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkTScopedComPtr_DEFINED
      9 #define SkTScopedComPtr_DEFINED
     10 
     11 #include "SkLeanWindows.h"
     12 
     13 #ifdef SK_BUILD_FOR_WIN
     14 
     15 template<typename T>
     16 class SkBlockComRef : public T {
     17 private:
     18     virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
     19     virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
     20     virtual ~SkBlockComRef() {}
     21 };
     22 
     23 template<typename T> T* SkRefComPtr(T* ptr) {
     24     ptr->AddRef();
     25     return ptr;
     26 }
     27 
     28 template<typename T> T* SkSafeRefComPtr(T* ptr) {
     29     if (ptr) {
     30         ptr->AddRef();
     31     }
     32     return ptr;
     33 }
     34 
     35 template<typename T>
     36 class SkTScopedComPtr {
     37 private:
     38     T *fPtr;
     39 
     40 public:
     41     constexpr SkTScopedComPtr() : fPtr(nullptr) {}
     42     constexpr SkTScopedComPtr(std::nullptr_t) : fPtr(nullptr) {}
     43     explicit SkTScopedComPtr(T *ptr) : fPtr(ptr) {}
     44     SkTScopedComPtr(SkTScopedComPtr&& that) : fPtr(that.release()) {}
     45     SkTScopedComPtr(const SkTScopedComPtr&) = delete;
     46 
     47     ~SkTScopedComPtr() { this->reset();}
     48 
     49     SkTScopedComPtr& operator=(SkTScopedComPtr&& that) {
     50         this->reset(that.release());
     51         return *this;
     52     }
     53     SkTScopedComPtr& operator=(const SkTScopedComPtr&) = delete;
     54     SkTScopedComPtr& operator=(std::nullptr_t) { this->reset(); return *this; }
     55 
     56     T &operator*() const { SkASSERT(fPtr != nullptr); return *fPtr; }
     57 
     58     explicit operator bool() const { return fPtr != nullptr; }
     59 
     60     SkBlockComRef<T> *operator->() const { return static_cast<SkBlockComRef<T>*>(fPtr); }
     61 
     62     /**
     63      * Returns the address of the underlying pointer.
     64      * This is dangerous -- it breaks encapsulation and the reference escapes.
     65      * Must only be used on instances currently pointing to NULL,
     66      * and only to initialize the instance.
     67      */
     68     T **operator&() { SkASSERT(fPtr == nullptr); return &fPtr; }
     69 
     70     T *get() const { return fPtr; }
     71 
     72     void reset(T* ptr = nullptr) {
     73         if (fPtr) {
     74             fPtr->Release();
     75         }
     76         fPtr = ptr;
     77     }
     78 
     79     void swap(SkTScopedComPtr<T>& that) {
     80         T* temp = this->fPtr;
     81         this->fPtr = that.fPtr;
     82         that.fPtr = temp;
     83     }
     84 
     85     T* release() {
     86         T* temp = this->fPtr;
     87         this->fPtr = nullptr;
     88         return temp;
     89     }
     90 };
     91 
     92 #endif  // SK_BUILD_FOR_WIN
     93 #endif  // SkTScopedComPtr_DEFINED
     94