diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-21 07:00:22 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-21 07:00:22 +0000 |
commit | b4966382d5d5b72c2fa1ba76aa045128eaf90418 (patch) | |
tree | f57004fa72e42181b6e3186528ca331ceb05cfd6 /base | |
parent | f44d1193f728c17cc4fd7adfe11a3fce82cddb9b (diff) | |
download | chromium_src-b4966382d5d5b72c2fa1ba76aa045128eaf90418.zip chromium_src-b4966382d5d5b72c2fa1ba76aa045128eaf90418.tar.gz chromium_src-b4966382d5d5b72c2fa1ba76aa045128eaf90418.tar.bz2 |
Move ScopedCoMem to base/win. This is to allow the class to be used from folders that aren't allowed to depend on chrome/common (and besides, ScopedCoMem belongs in base/win anyway).
I'm also adding a DCHECK to ScopedComInitializer that checks if the construction thread is the same as the destruction thread. The reason for this is that I've noticed cases where an instance is created on the heap (as opposed to the usual stack usecase) which could leave the door open to incorrect COM uninitialization.
Review URL: http://codereview.chromium.org/8354035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106687 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/win/scoped_co_mem.h | 65 | ||||
-rw-r--r-- | base/win/scoped_com_initializer.h | 26 |
3 files changed, 89 insertions, 3 deletions
diff --git a/base/base.gypi b/base/base.gypi index b3a97af..e2f0a7d 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -370,6 +370,7 @@ 'win/resource_util.h', 'win/scoped_bstr.cc', 'win/scoped_bstr.h', + 'win/scoped_co_mem.h', 'win/scoped_com_initializer.h', 'win/scoped_comptr.h', 'win/scoped_gdi_object.h', diff --git a/base/win/scoped_co_mem.h b/base/win/scoped_co_mem.h new file mode 100644 index 0000000..ccbe707 --- /dev/null +++ b/base/win/scoped_co_mem.h @@ -0,0 +1,65 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_WIN_SCOPED_CO_MEM_H_ +#define BASE_WIN_SCOPED_CO_MEM_H_ +#pragma once + +#include <objbase.h> + +#include "base/basictypes.h" +#include "base/logging.h" + +namespace base { +namespace win { + +// Simple scoped memory releaser class for COM allocated memory. +// Example: +// base::win::ScopedCoMem<ITEMIDLIST> file_item; +// SHGetSomeInfo(&file_item, ...); +// ... +// return; <-- memory released +template<typename T> +class ScopedCoMem { + public: + ScopedCoMem() : mem_ptr_(NULL) {} + ~ScopedCoMem() { + Reset(NULL); + } + + T** operator&() { // NOLINT + DCHECK(mem_ptr_ == NULL); // To catch memory leaks. + return &mem_ptr_; + } + + operator T*() { + return mem_ptr_; + } + + T* operator->() { + DCHECK(mem_ptr_ != NULL); + return mem_ptr_; + } + + const T* operator->() const { + DCHECK(mem_ptr_ != NULL); + return mem_ptr_; + } + + void Reset(T* ptr) { + if (mem_ptr_) + CoTaskMemFree(mem_ptr_); + mem_ptr_ = ptr; + } + + private: + T* mem_ptr_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCoMem); +}; + +} // namespace win +} // namespace base + +#endif // BASE_WIN_SCOPED_CO_MEM_H_ diff --git a/base/win/scoped_com_initializer.h b/base/win/scoped_com_initializer.h index 0ea5199..0cf1ac7 100644 --- a/base/win/scoped_com_initializer.h +++ b/base/win/scoped_com_initializer.h @@ -7,6 +7,7 @@ #pragma once #include "base/basictypes.h" +#include "base/logging.h" #include "build/build_config.h" #if defined(OS_WIN) @@ -24,15 +25,20 @@ class ScopedCOMInitializer { enum SelectMTA { kMTA }; // Constructor for STA initialization. - ScopedCOMInitializer() : hr_(CoInitialize(NULL)) { + ScopedCOMInitializer() { + Initialize(COINIT_APARTMENTTHREADED); } // Constructor for MTA initialization. - explicit ScopedCOMInitializer(SelectMTA mta) - : hr_(CoInitializeEx(NULL, COINIT_MULTITHREADED)) { + explicit ScopedCOMInitializer(SelectMTA mta) { + Initialize(COINIT_MULTITHREADED); } ScopedCOMInitializer::~ScopedCOMInitializer() { +#ifndef NDEBUG + // Using the windows API directly to avoid dependency on platform_thread. + DCHECK_EQ(GetCurrentThreadId(), thread_id_); +#endif if (SUCCEEDED(hr_)) CoUninitialize(); } @@ -40,7 +46,21 @@ class ScopedCOMInitializer { bool succeeded() const { return SUCCEEDED(hr_); } private: + void Initialize(COINIT init) { +#ifndef NDEBUG + thread_id_ = GetCurrentThreadId(); +#endif + hr_ = CoInitializeEx(NULL, init); + } + HRESULT hr_; +#ifndef NDEBUG + // In debug builds we use this variable to catch a potential bug where a + // ScopedCOMInitializer instance is deleted on a different thread than it + // was initially created on. If that ever happens it can have bad + // consequences and the cause can be tricky to track down. + DWORD thread_id_; +#endif DISALLOW_COPY_AND_ASSIGN(ScopedCOMInitializer); }; |