Chromium Code Reviews| Index: base/win/scoped_comptr.h |
| diff --git a/base/win/scoped_comptr.h b/base/win/scoped_comptr.h |
| index 9442672054a90f99a47d49831ad197986bbbacd7..315d321cbb8031dc906a5d165a3118e3835e4011 100644 |
| --- a/base/win/scoped_comptr.h |
| +++ b/base/win/scoped_comptr.h |
| @@ -8,16 +8,14 @@ |
| #include <unknwn.h> |
| #include "base/logging.h" |
| -#include "base/memory/ref_counted.h" |
| namespace base { |
| namespace win { |
| +// DEPRECATED: Use Microsoft::WRL::ComPtr instead. |
| // A fairly minimalistic smart class for COM interface pointers. |
| -// Uses scoped_refptr for the basic smart pointer functionality |
| -// and adds a few IUnknown specific services. |
| template <class Interface, const IID* interface_id = &__uuidof(Interface)> |
| -class ScopedComPtr : public scoped_refptr<Interface> { |
| +class ScopedComPtr { |
| public: |
| // Utility template to prevent users of ScopedComPtr from calling AddRef |
| // and/or Release() without going through the ScopedComPtr class. |
| @@ -28,16 +26,17 @@ class ScopedComPtr : public scoped_refptr<Interface> { |
| STDMETHOD_(ULONG, Release)() = 0; |
| }; |
| - typedef scoped_refptr<Interface> ParentClass; |
| - |
| ScopedComPtr() { |
| } |
| - explicit ScopedComPtr(Interface* p) : ParentClass(p) { |
| + explicit ScopedComPtr(Interface* p) : ptr_(p) { |
| + if (ptr_) |
| + ptr_->AddRef(); |
| } |
| - ScopedComPtr(const ScopedComPtr<Interface, interface_id>& p) |
| - : ParentClass(p) { |
| + ScopedComPtr(const ScopedComPtr<Interface, interface_id>& p) : ptr_(p.get()) { |
| + if (ptr_) |
| + ptr_->AddRef(); |
| } |
| ~ScopedComPtr() { |
| @@ -46,31 +45,37 @@ class ScopedComPtr : public scoped_refptr<Interface> { |
| static_assert( |
| sizeof(ScopedComPtr<Interface, interface_id>) == sizeof(Interface*), |
| "ScopedComPtrSize"); |
| + Release(); |
| } |
| + Interface* get() const { return ptr_; } |
| + |
| + explicit operator bool() const { return ptr_ != nullptr; } |
| + |
| // Explicit Release() of the held object. Useful for reuse of the |
| // ScopedComPtr instance. |
| // Note that this function equates to IUnknown::Release and should not |
| // be confused with e.g. unique_ptr::release(). |
| void Release() { |
| - if (this->ptr_ != NULL) { |
| - this->ptr_->Release(); |
| - this->ptr_ = NULL; |
| + Interface* temp = ptr_; |
| + if (temp) { |
| + ptr_ = nullptr; |
|
scottmg
2017/04/03 18:23:22
I assume you swapped these on purpose?
robliao
2017/04/03 19:22:21
Yep. I figured I would go ahead and align with Com
|
| + temp->Release(); |
| } |
| } |
| // Sets the internal pointer to NULL and returns the held object without |
| // releasing the reference. |
| Interface* Detach() { |
| - Interface* p = this->ptr_; |
| - this->ptr_ = NULL; |
| + Interface* p = ptr_; |
| + ptr_ = nullptr; |
| return p; |
| } |
| // Accepts an interface pointer that has already been addref-ed. |
| void Attach(Interface* p) { |
| - DCHECK(!this->ptr_); |
| - this->ptr_ = p; |
| + DCHECK(!ptr_); |
| + ptr_ = p; |
| } |
| // Retrieves the pointer address. |
| @@ -78,8 +83,8 @@ class ScopedComPtr : public scoped_refptr<Interface> { |
| // The function DCHECKs on the current value being NULL. |
| // Usage: Foo(p.Receive()); |
| Interface** Receive() { |
| - DCHECK(!this->ptr_) << "Object leak. Pointer must be NULL"; |
| - return &this->ptr_; |
| + DCHECK(!ptr_) << "Object leak. Pointer must be NULL"; |
| + return &ptr_; |
| } |
| // A convenience for whenever a void pointer is needed as an out argument. |
| @@ -89,43 +94,44 @@ class ScopedComPtr : public scoped_refptr<Interface> { |
| template <class Query> |
| HRESULT QueryInterface(Query** p) { |
| - DCHECK(p != NULL); |
| - DCHECK(this->ptr_ != NULL); |
| + DCHECK(p); |
| + DCHECK(ptr_); |
| // IUnknown already has a template version of QueryInterface |
| // so the iid parameter is implicit here. The only thing this |
| // function adds are the DCHECKs. |
| - return this->ptr_->QueryInterface(p); |
| + return ptr_->QueryInterface(p); |
| } |
| // QI for times when the IID is not associated with the type. |
| HRESULT QueryInterface(const IID& iid, void** obj) { |
| - DCHECK(obj != NULL); |
| - DCHECK(this->ptr_ != NULL); |
| - return this->ptr_->QueryInterface(iid, obj); |
| + DCHECK(obj); |
| + DCHECK(ptr_); |
| + return ptr_->QueryInterface(iid, obj); |
| } |
| // Queries |other| for the interface this object wraps and returns the |
| // error code from the other->QueryInterface operation. |
| HRESULT QueryFrom(IUnknown* object) { |
| - DCHECK(object != NULL); |
| + DCHECK(object); |
| return object->QueryInterface(Receive()); |
| } |
| // Convenience wrapper around CoCreateInstance |
| - HRESULT CreateInstance(const CLSID& clsid, IUnknown* outer = NULL, |
| + HRESULT CreateInstance(const CLSID& clsid, |
| + IUnknown* outer = nullptr, |
| DWORD context = CLSCTX_ALL) { |
| - DCHECK(!this->ptr_); |
| + DCHECK(!ptr_); |
| HRESULT hr = ::CoCreateInstance(clsid, outer, context, *interface_id, |
| - reinterpret_cast<void**>(&this->ptr_)); |
| + reinterpret_cast<void**>(&ptr_)); |
| return hr; |
| } |
| // Checks if the identity of |other| and this object is the same. |
| bool IsSameObject(IUnknown* other) { |
| - if (!other && !this->ptr_) |
| + if (!other && !ptr_) |
| return true; |
| - if (!other || !this->ptr_) |
| + if (!other || !ptr_) |
| return false; |
| ScopedComPtr<IUnknown> my_identity; |
| @@ -148,20 +154,103 @@ class ScopedComPtr : public scoped_refptr<Interface> { |
| // by statically casting the ScopedComPtr instance to the wrapped interface |
| // and then making the call... but generally that shouldn't be necessary. |
| BlockIUnknownMethods* operator->() const { |
| - DCHECK(this->ptr_ != NULL); |
| - return reinterpret_cast<BlockIUnknownMethods*>(this->ptr_); |
| + DCHECK(ptr_); |
| + return reinterpret_cast<BlockIUnknownMethods*>(ptr_); |
| + } |
| + |
| + ScopedComPtr<Interface, interface_id>& operator=(Interface* rhs) { |
| + // AddRef first so that self assignment should work |
| + if (rhs) |
| + rhs->AddRef(); |
| + Interface* old_ptr = ptr_; |
| + ptr_ = rhs; |
| + if (old_ptr) |
| + old_ptr->Release(); |
| + return *this; |
| } |
| - // Pull in operator=() from the parent class. |
| - using scoped_refptr<Interface>::operator=; |
| + ScopedComPtr<Interface, interface_id>& operator=( |
| + const ScopedComPtr<Interface, interface_id>& rhs) { |
| + return *this = rhs.ptr_; |
| + } |
| - // static methods |
| + Interface& operator*() const { |
| + DCHECK(ptr_); |
| + return *ptr_; |
| + } |
| + bool operator==(const ScopedComPtr<Interface, interface_id>& rhs) const { |
| + return ptr_ == rhs.get(); |
| + } |
| + |
| + template <typename U> |
| + bool operator==(const ScopedComPtr<U>& rhs) const { |
| + return ptr_ == rhs.get(); |
| + } |
| + |
| + template <typename U> |
| + bool operator==(const U* rhs) const { |
| + return ptr_ == rhs; |
| + } |
| + |
| + bool operator!=(const ScopedComPtr<Interface, interface_id>& rhs) const { |
| + return ptr_ != rhs.get(); |
| + } |
| + |
| + template <typename U> |
| + bool operator!=(const ScopedComPtr<U>& rhs) const { |
| + return ptr_ != rhs.get(); |
| + } |
| + |
| + template <typename U> |
| + bool operator!=(const U* rhs) const { |
| + return ptr_ != rhs; |
| + } |
| + |
| + // static methods |
| static const IID& iid() { |
| return *interface_id; |
| } |
| + |
| + private: |
| + Interface* ptr_ = nullptr; |
| }; |
| +template <typename T, typename U> |
| +bool operator==(const T* lhs, const ScopedComPtr<U>& rhs) { |
| + return lhs == rhs.get(); |
| +} |
| + |
| +template <typename T> |
| +bool operator==(const ScopedComPtr<T>& lhs, std::nullptr_t null) { |
| + return !static_cast<bool>(lhs); |
| +} |
| + |
| +template <typename T> |
| +bool operator==(std::nullptr_t null, const ScopedComPtr<T>& rhs) { |
| + return !static_cast<bool>(rhs); |
| +} |
| + |
| +template <typename T, typename U> |
| +bool operator!=(const T* lhs, const ScopedComPtr<U>& rhs) { |
| + return !operator==(lhs, rhs); |
| +} |
| + |
| +template <typename T> |
| +bool operator!=(const ScopedComPtr<T>& lhs, std::nullptr_t null) { |
| + return !operator==(lhs, null); |
| +} |
| + |
| +template <typename T> |
| +bool operator!=(std::nullptr_t null, const ScopedComPtr<T>& rhs) { |
| + return !operator==(null, rhs); |
| +} |
| + |
| +template <typename T> |
| +std::ostream& operator<<(std::ostream& out, const ScopedComPtr<T>& p) { |
| + return out << p.get(); |
| +} |
| + |
| } // namespace win |
| } // namespace base |