diff options
author | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-09 03:27:08 +0000 |
---|---|---|
committer | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-09 03:27:08 +0000 |
commit | 0a646946bcb2d40e003494ad32721d333f47382b (patch) | |
tree | 22dab319734c75f0c8e3a6d8accbdeca1f2f36ed | |
parent | 8687244a01e4333ed0edb429bdefbf88f83e965b (diff) | |
download | chromium_src-0a646946bcb2d40e003494ad32721d333f47382b.zip chromium_src-0a646946bcb2d40e003494ad32721d333f47382b.tar.gz chromium_src-0a646946bcb2d40e003494ad32721d333f47382b.tar.bz2 |
A basic wrapper for a windows event object that encapsulates the way we often use windows events. This API is not meant to be compatible with ObjectWatcher or MessageLoop::WatchObject. This API is meant to be easily ported to Mac & Linux using a traditional mutex and condition variable pairing.
There's nothing to test here since the implementation is such a thin wrapper around Win32 APIs. However, once we go off to implement a posix version, we'll need some tests.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@620 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/SConscript | 1 | ||||
-rw-r--r-- | base/build/base.vcproj | 8 | ||||
-rw-r--r-- | base/waitable_event.h | 94 | ||||
-rw-r--r-- | base/waitable_event_win.cc | 84 |
4 files changed, 187 insertions, 0 deletions
diff --git a/base/SConscript b/base/SConscript index b37b6f4..719e29b 100644 --- a/base/SConscript +++ b/base/SConscript @@ -123,6 +123,7 @@ if env['PLATFORM'] == 'win32': 'sys_string_conversions_win.cc', 'thread_local_storage_win.cc', 'time_win.cc', + 'waitable_event_win.cc', ]) if env['PLATFORM'] == 'darwin': diff --git a/base/build/base.vcproj b/base/build/base.vcproj index 3e2cd15..9a732b0 100644 --- a/base/build/base.vcproj +++ b/base/build/base.vcproj @@ -730,6 +730,14 @@ > </File> <File + RelativePath="..\waitable_event.h" + > + </File> + <File + RelativePath="..\waitable_event_win.cc" + > + </File> + <File RelativePath="..\watchdog.cc" > </File> diff --git a/base/waitable_event.h b/base/waitable_event.h new file mode 100644 index 0000000..778dabf --- /dev/null +++ b/base/waitable_event.h @@ -0,0 +1,94 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef BASE_WAITABLE_EVENT_H_ +#define BASE_WAITABLE_EVENT_H_ + +#include "base/time.h" + +#if defined(OS_WIN) +typedef void* HANDLE; +#endif + +namespace base { + +// A WaitableEvent can be a useful thread synchronization tool when you want to +// allow one thread to wait for another thread to finish some work. +// +// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to +// protect a simple boolean value. However, if you find yourself using a +// WaitableEvent in conjunction with a Lock to wait for a more complex state +// change (e.g., for an item to be added to a queue), then you should probably +// be using a ConditionVariable instead of a WaitableEvent. +// +// NOTE: On Windows, this class provides a subset of the functionality afforded +// by a Windows event object. This is intentional. If you are writing Windows +// specific code and you need other features of a Windows event, then you might +// be better off just using an Windows event directly. +// +class WaitableEvent { + public: + // If manual_reset is true, then to set the event state to non-signaled, a + // consumer must call the Reset method. If this parameter is false, then the + // system automatically resets the event state to non-signaled after a single + // waiting thread has been released. + WaitableEvent(bool manual_reset, bool initially_signaled); + + // WARNING: Destroying a WaitableEvent while threads are waiting on it is not + // supported. Doing so will cause crashes or other instability. + ~WaitableEvent(); + + // Put the event in the un-signaled state. + void Reset(); + + // Put the event in the signaled state. Causing any thread blocked on Wait + // to be woken up. + void Signal(); + + // Returns true if the event is in the signaled state, else false. + bool IsSignaled(); + + // Wait indefinitely for the event to be signaled. Returns true if the event + // was signaled, else false is returned to indicate that waiting failed. + bool Wait(); + + // Wait up until max_time has passed for the event to be signaled. Returns + // true if the event was signaled. If this method returns false, then it + // does not necessarily mean that max_time was exceeded. + bool TimedWait(const TimeDelta& max_time); + + private: +#if defined(OS_WIN) + HANDLE event_; +#endif +}; + +} // namespace base + +#endif // BASE_WAITABLE_EVENT_H_ diff --git a/base/waitable_event_win.cc b/base/waitable_event_win.cc new file mode 100644 index 0000000..58fbfde --- /dev/null +++ b/base/waitable_event_win.cc @@ -0,0 +1,84 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/waitable_event.h" + +#include <windows.h> +#include "base/logging.h" + +namespace base { + +WaitableEvent::WaitableEvent(bool manual_reset, bool signaled) + : event_(CreateEvent(NULL, manual_reset, signaled, NULL)) { + // We're probably going to crash anyways if this is ever NULL, so we might as + // well make our stack reports more informative by crashing here. + CHECK(event_); +} + +WaitableEvent::~WaitableEvent() { + CloseHandle(event_); +} + +void WaitableEvent::Reset() { + ResetEvent(event_); +} + +void WaitableEvent::Signal() { + SetEvent(event_); +} + +bool WaitableEvent::IsSignaled() { + return TimedWait(TimeDelta::FromMilliseconds(0)); +} + +bool WaitableEvent::Wait() { + DWORD result = WaitForSingleObject(event_, INFINITE); + // It is most unexpected that this should ever fail. Help consumers learn + // about it if it should ever fail. + DCHECK(result == WAIT_OBJECT_0) << "WaitForSingleObject failed"; + return result == WAIT_OBJECT_0; +} + +bool WaitableEvent::TimedWait(const TimeDelta& max_time) { + int32 timeout = static_cast<int32>(max_time.InMilliseconds()); + DWORD result = WaitForSingleObject(event_, timeout); + switch (result) { + case WAIT_OBJECT_0: + return true; + case WAIT_TIMEOUT: + return false; + } + // It is most unexpected that this should ever fail. Help consumers learn + // about it if it should ever fail. + NOTREACHED() << "WaitForSingleObject failed"; + return false; + +} + +} // namespace base |