michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_WIN_SCOPED_HANDLE_H_ michael@0: #define BASE_WIN_SCOPED_HANDLE_H_ michael@0: michael@0: #include michael@0: michael@0: #include "base/base_export.h" michael@0: #include "base/basictypes.h" michael@0: #include "base/location.h" michael@0: #include "base/logging.h" michael@0: #include "base/move.h" michael@0: michael@0: namespace base { michael@0: namespace win { michael@0: michael@0: // TODO(rvargas): remove this with the rest of the verifier. michael@0: #if defined(COMPILER_MSVC) michael@0: // MSDN says to #include , but that breaks the VS2005 build. michael@0: extern "C" { michael@0: void* _ReturnAddress(); michael@0: } michael@0: #define BASE_WIN_GET_CALLER _ReturnAddress() michael@0: #elif defined(COMPILER_GCC) michael@0: #define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\ michael@0: __builtin_return_address(0)) michael@0: #endif michael@0: michael@0: // Generic wrapper for raw handles that takes care of closing handles michael@0: // automatically. The class interface follows the style of michael@0: // the ScopedStdioHandle class with a few additions: michael@0: // - IsValid() method can tolerate multiple invalid handle values such as NULL michael@0: // and INVALID_HANDLE_VALUE (-1) for Win32 handles. michael@0: // - Receive() method allows to receive a handle value from a function that michael@0: // takes a raw handle pointer only. michael@0: template michael@0: class GenericScopedHandle { michael@0: MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue) michael@0: michael@0: public: michael@0: typedef typename Traits::Handle Handle; michael@0: michael@0: // Helper object to contain the effect of Receive() to the function that needs michael@0: // a pointer, and allow proper tracking of the handle. michael@0: class Receiver { michael@0: public: michael@0: explicit Receiver(GenericScopedHandle* owner) michael@0: : handle_(Traits::NullHandle()), michael@0: owner_(owner) {} michael@0: ~Receiver() { owner_->Set(handle_); } michael@0: michael@0: operator Handle*() { return &handle_; } michael@0: michael@0: private: michael@0: Handle handle_; michael@0: GenericScopedHandle* owner_; michael@0: }; michael@0: michael@0: GenericScopedHandle() : handle_(Traits::NullHandle()) {} michael@0: michael@0: explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { michael@0: Set(handle); michael@0: } michael@0: michael@0: // Move constructor for C++03 move emulation of this type. michael@0: GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) { michael@0: Set(other.object->Take()); michael@0: } michael@0: michael@0: ~GenericScopedHandle() { michael@0: Close(); michael@0: } michael@0: michael@0: bool IsValid() const { michael@0: return Traits::IsHandleValid(handle_); michael@0: } michael@0: michael@0: // Move operator= for C++03 move emulation of this type. michael@0: GenericScopedHandle& operator=(RValue other) { michael@0: if (this != other.object) { michael@0: Set(other.object->Take()); michael@0: } michael@0: return *this; michael@0: } michael@0: michael@0: void Set(Handle handle) { michael@0: if (handle_ != handle) { michael@0: Close(); michael@0: michael@0: if (Traits::IsHandleValid(handle)) { michael@0: handle_ = handle; michael@0: Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER, michael@0: tracked_objects::GetProgramCounter()); michael@0: } michael@0: } michael@0: } michael@0: michael@0: Handle Get() const { michael@0: return handle_; michael@0: } michael@0: michael@0: operator Handle() const { michael@0: return handle_; michael@0: } michael@0: michael@0: // This method is intended to be used with functions that require a pointer to michael@0: // a destination handle, like so: michael@0: // void CreateRequiredHandle(Handle* out_handle); michael@0: // ScopedHandle a; michael@0: // CreateRequiredHandle(a.Receive()); michael@0: Receiver Receive() { michael@0: DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL"; michael@0: return Receiver(this); michael@0: } michael@0: michael@0: // Transfers ownership away from this object. michael@0: Handle Take() { michael@0: Handle temp = handle_; michael@0: handle_ = Traits::NullHandle(); michael@0: if (Traits::IsHandleValid(temp)) { michael@0: Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER, michael@0: tracked_objects::GetProgramCounter()); michael@0: } michael@0: return temp; michael@0: } michael@0: michael@0: // Explicitly closes the owned handle. michael@0: void Close() { michael@0: if (Traits::IsHandleValid(handle_)) { michael@0: Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER, michael@0: tracked_objects::GetProgramCounter()); michael@0: michael@0: if (!Traits::CloseHandle(handle_)) michael@0: CHECK(false); michael@0: michael@0: handle_ = Traits::NullHandle(); michael@0: } michael@0: } michael@0: michael@0: private: michael@0: Handle handle_; michael@0: }; michael@0: michael@0: #undef BASE_WIN_GET_CALLER michael@0: michael@0: // The traits class for Win32 handles that can be closed via CloseHandle() API. michael@0: class HandleTraits { michael@0: public: michael@0: typedef HANDLE Handle; michael@0: michael@0: // Closes the handle. michael@0: static bool CloseHandle(HANDLE handle) { michael@0: return ::CloseHandle(handle) != FALSE; michael@0: } michael@0: michael@0: // Returns true if the handle value is valid. michael@0: static bool IsHandleValid(HANDLE handle) { michael@0: return handle != NULL && handle != INVALID_HANDLE_VALUE; michael@0: } michael@0: michael@0: // Returns NULL handle value. michael@0: static HANDLE NullHandle() { michael@0: return NULL; michael@0: } michael@0: michael@0: private: michael@0: DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); michael@0: }; michael@0: michael@0: // Do-nothing verifier. michael@0: class DummyVerifierTraits { michael@0: public: michael@0: typedef HANDLE Handle; michael@0: michael@0: static void StartTracking(HANDLE handle, const void* owner, michael@0: const void* pc1, const void* pc2) {} michael@0: static void StopTracking(HANDLE handle, const void* owner, michael@0: const void* pc1, const void* pc2) {} michael@0: michael@0: private: michael@0: DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits); michael@0: }; michael@0: michael@0: // Performs actual run-time tracking. michael@0: class BASE_EXPORT VerifierTraits { michael@0: public: michael@0: typedef HANDLE Handle; michael@0: michael@0: static void StartTracking(HANDLE handle, const void* owner, michael@0: const void* pc1, const void* pc2); michael@0: static void StopTracking(HANDLE handle, const void* owner, michael@0: const void* pc1, const void* pc2); michael@0: michael@0: private: michael@0: DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits); michael@0: }; michael@0: michael@0: typedef GenericScopedHandle ScopedHandle; michael@0: michael@0: } // namespace win michael@0: } // namespace base michael@0: michael@0: #endif // BASE_SCOPED_HANDLE_WIN_H_