Commit 5f29c1d6 authored by alexeypa@chromium.org's avatar alexeypa@chromium.org

Making GenericScopedHandle capable of handling handle types other than HANDLE.


Review URL: http://codereview.chromium.org/9582045

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124980 0039d316-1c4b-4281-b951-d872f2087c98
parent 93079299
...@@ -14,87 +14,100 @@ ...@@ -14,87 +14,100 @@
namespace base { namespace base {
namespace win { namespace win {
// Used so we always remember to close the handle. // Generic wrapper for raw handles that takes care of closing handles
// The class interface matches that of ScopedStdioHandle in addition to an // automatically. The class interface follows the style of
// IsValid() method since invalid handles on windows can be either NULL or // the ScopedStdioHandle class with a few additions:
// INVALID_HANDLE_VALUE (-1). // - IsValid() method can tolerate multiple invalid handle values such as NULL
// // and INVALID_HANDLE_VALUE (-1) for Win32 handles.
// Example: // - Receive() method allows to receive a handle value from a function that
// ScopedHandle hfile(CreateFile(...)); // takes a raw handle pointer only.
// 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();
template <class Traits> template <class Traits>
class GenericScopedHandle { class GenericScopedHandle {
public: public:
GenericScopedHandle() : handle_(NULL) { typedef typename Traits::Handle Handle;
}
GenericScopedHandle() : handle_(Traits::NullHandle()) {}
explicit GenericScopedHandle(HANDLE h) : handle_(NULL) { explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
Set(h); Set(handle);
} }
~GenericScopedHandle() { ~GenericScopedHandle() {
Close(); Close();
} }
// Use this instead of comparing to INVALID_HANDLE_VALUE to pick up our NULL
// usage for errors.
bool IsValid() const { bool IsValid() const {
return handle_ != NULL; return Traits::IsHandleValid(handle_);
} }
void Set(HANDLE new_handle) { void Set(Handle handle) {
Close(); if (handle_ != handle) {
Close();
// Windows is inconsistent about invalid handles, so we always use NULL if (Traits::IsHandleValid(handle)) {
if (new_handle != INVALID_HANDLE_VALUE) handle_ = handle;
handle_ = new_handle; }
}
} }
HANDLE Get() { Handle Get() const {
return handle_; return handle_;
} }
operator HANDLE() { return handle_; } operator Handle() const {
return handle_;
}
HANDLE* Receive() { Handle* Receive() {
DCHECK(!handle_) << "Handle must be NULL"; DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL";
return &handle_; return &handle_;
} }
HANDLE Take() { // Transfers ownership away from this object.
// transfers ownership away from this object Handle Take() {
HANDLE h = handle_; Handle temp = handle_;
handle_ = NULL; handle_ = Traits::NullHandle();
return h; return temp;
} }
// Explicitly closes the owned handle.
void Close() { void Close() {
if (handle_) { if (Traits::IsHandleValid(handle_)) {
if (!Traits::CloseHandle(handle_)) { if (!Traits::CloseHandle(handle_)) {
NOTREACHED(); NOTREACHED();
} }
handle_ = NULL; handle_ = Traits::NullHandle();
} }
} }
private: private:
HANDLE handle_; Handle handle_;
DISALLOW_COPY_AND_ASSIGN(GenericScopedHandle); DISALLOW_COPY_AND_ASSIGN(GenericScopedHandle);
}; };
// The traits class for Win32 handles that can be closed via CloseHandle() API.
class HandleTraits { class HandleTraits {
public: public:
typedef HANDLE Handle;
// Closes the handle.
static bool CloseHandle(HANDLE handle) { static bool CloseHandle(HANDLE handle) {
return ::CloseHandle(handle) != FALSE; 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; typedef GenericScopedHandle<HandleTraits> ScopedHandle;
......
...@@ -35,9 +35,22 @@ namespace { ...@@ -35,9 +35,22 @@ namespace {
class PrinterChangeHandleTraits { class PrinterChangeHandleTraits {
public: public:
typedef HANDLE Handle;
static bool CloseHandle(HANDLE handle) { static bool CloseHandle(HANDLE handle) {
return ::FindClosePrinterChangeNotification(handle) != FALSE; return ::FindClosePrinterChangeNotification(handle) != FALSE;
} }
static bool IsHandleValid(HANDLE handle) {
return handle != NULL;
}
static HANDLE NullHandle() {
return NULL;
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PrinterChangeHandleTraits);
}; };
typedef base::win::GenericScopedHandle<PrinterChangeHandleTraits> typedef base::win::GenericScopedHandle<PrinterChangeHandleTraits>
......
...@@ -20,9 +20,22 @@ namespace printing { ...@@ -20,9 +20,22 @@ namespace printing {
class PrinterHandleTraits { class PrinterHandleTraits {
public: public:
typedef HANDLE Handle;
static bool CloseHandle(HANDLE handle) { static bool CloseHandle(HANDLE handle) {
return ::ClosePrinter(handle) != FALSE; return ::ClosePrinter(handle) != FALSE;
} }
static bool IsHandleValid(HANDLE handle) {
return handle != NULL;
}
static HANDLE NullHandle() {
return NULL;
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PrinterHandleTraits);
}; };
typedef base::win::GenericScopedHandle<PrinterHandleTraits> ScopedPrinterHandle; typedef base::win::GenericScopedHandle<PrinterHandleTraits> ScopedPrinterHandle;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment