Index: base/win/scoped_handle.h |
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h |
index 44e723f941a2b78af9a83a895be1d31eeef0f4c0..b89219c45ee3c8fdd6f9a07b3de1ad3b831d9129 100644 |
--- a/base/win/scoped_handle.h |
+++ b/base/win/scoped_handle.h |
@@ -14,87 +14,100 @@ |
namespace base { |
namespace win { |
-// Used so we always remember to close the handle. |
-// The class interface matches that of ScopedStdioHandle in addition to an |
-// IsValid() method since invalid handles on windows can be either NULL or |
-// INVALID_HANDLE_VALUE (-1). |
-// |
-// Example: |
-// ScopedHandle hfile(CreateFile(...)); |
-// if (!hfile.Get()) |
-// ...process error |
-// ReadFile(hfile.Get(), ...); |
-// |
-// To sqirrel the handle away somewhere else: |
-// secret_handle_ = hfile.Take(); |
-// |
-// To explicitly close the handle: |
-// hfile.Close(); |
+// Generic wrapper for raw handles that takes care of closing handles |
+// automatically. The class interface follows the style of |
+// the ScopedStdioHandle class with a few additions: |
+// - IsValid() method can tolerate multiple invalid handle values such as NULL |
+// and INVALID_HANDLE_VALUE (-1) for Win32 handles. |
+// - Receive() method allows to receive a handle value from a function that |
+// takes a raw handle pointer only. |
template <class Traits> |
class GenericScopedHandle { |
public: |
- GenericScopedHandle() : handle_(NULL) { |
- } |
+ typedef typename Traits::Handle Handle; |
+ |
+ GenericScopedHandle() : handle_(Traits::NullHandle()) {} |
- explicit GenericScopedHandle(HANDLE h) : handle_(NULL) { |
- Set(h); |
+ explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { |
+ Set(handle); |
} |
~GenericScopedHandle() { |
Close(); |
} |
- // Use this instead of comparing to INVALID_HANDLE_VALUE to pick up our NULL |
- // usage for errors. |
bool IsValid() const { |
- return handle_ != NULL; |
+ return Traits::IsHandleValid(handle_); |
} |
- void Set(HANDLE new_handle) { |
- Close(); |
+ void Set(Handle handle) { |
+ if (handle_ != handle) { |
+ Close(); |
- // Windows is inconsistent about invalid handles, so we always use NULL |
- if (new_handle != INVALID_HANDLE_VALUE) |
- handle_ = new_handle; |
+ if (Traits::IsHandleValid(handle)) { |
+ handle_ = handle; |
+ } |
+ } |
} |
- HANDLE Get() { |
+ Handle Get() const { |
return handle_; |
} |
- operator HANDLE() { return handle_; } |
+ operator Handle() const { |
+ return handle_; |
+ } |
- HANDLE* Receive() { |
- DCHECK(!handle_) << "Handle must be NULL"; |
+ Handle* Receive() { |
+ DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL"; |
return &handle_; |
} |
- HANDLE Take() { |
- // transfers ownership away from this object |
- HANDLE h = handle_; |
- handle_ = NULL; |
- return h; |
+ // Transfers ownership away from this object. |
+ Handle Take() { |
+ Handle temp = handle_; |
+ handle_ = Traits::NullHandle(); |
+ return temp; |
} |
+ // Explicitly closes the owned handle. |
void Close() { |
- if (handle_) { |
+ if (Traits::IsHandleValid(handle_)) { |
if (!Traits::CloseHandle(handle_)) { |
NOTREACHED(); |
} |
- handle_ = NULL; |
+ handle_ = Traits::NullHandle(); |
} |
} |
private: |
- HANDLE handle_; |
+ Handle handle_; |
+ |
DISALLOW_COPY_AND_ASSIGN(GenericScopedHandle); |
}; |
+// The traits class for Win32 handles that can be closed via CloseHandle() API. |
class HandleTraits { |
public: |
+ typedef HANDLE Handle; |
+ |
+ // Closes the handle. |
static bool CloseHandle(HANDLE handle) { |
return ::CloseHandle(handle) != FALSE; |
} |
+ |
+ // Returns true if the handle value is valid. |
+ static bool IsHandleValid(HANDLE handle) { |
+ return handle != NULL && handle != INVALID_HANDLE_VALUE; |
+ } |
+ |
+ // Returns NULL handle value. |
+ static HANDLE NullHandle() { |
+ return NULL; |
+ } |
+ |
+ private: |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); |
}; |
typedef GenericScopedHandle<HandleTraits> ScopedHandle; |