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