diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-15 22:25:11 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-15 22:25:11 +0000 |
commit | 1c4947ffee0b7f5672737b542eb6adf466fcb223 (patch) | |
tree | ca2b1631479523a3a397fac842fe0870f422193f /base/waitable_event_watcher_unittest.cc | |
parent | c0ce93d64e2374f29acf2130c5324dc54762f0fa (diff) | |
download | chromium_src-1c4947ffee0b7f5672737b542eb6adf466fcb223.zip chromium_src-1c4947ffee0b7f5672737b542eb6adf466fcb223.tar.gz chromium_src-1c4947ffee0b7f5672737b542eb6adf466fcb223.tar.bz2 |
WaitableEvent is the replacement for Windows events. Previously in the code, a HANDLE from CreateEvent was used for signaling, both within a process and across processes.
WaitableEvent is the cross platform replacement for this. To convert:
* HANDLE -> base::WaitableEvent*
* ScopedHandle -> scoped_ptr<base::WaitableEvent>
* CreateEvent -> new base::WaitableEvent
* SetEvent -> base::WaitableEvent::Signal
* ResetEvent -> base::WaitableEvent::Reset
* ObjectWatcher -> base::WaitableEventWatcher
* WaitForMultipleObjects -> static base::WaitableEvent::WaitMany
ObjectWatcher remains for Windows specific code. WaitableEventWatcher has an identical interface save,
* It uses WaitableEvents, not HANDLEs
* It returns void from StartWatching and StopWatcher, rather than errors. System internal errors are fatal to the address space
IMPORTANT: There are semantic differences between the different platforms. WaitableEvents on Windows are implemented on top of events. Windows events work across process and this is used mostly for modal dialog support. Windows events can be duplicated with DuplicateHandle.
On other platforms, WaitableEvent works only within a single process. In the future we shall have to replace the current uses of cross-process events with IPCs.
BEWARE: HANDLE, on Windows, is a void *. Since any pointer type coerces to void *, you can pass a WaitableEvent * where a HANDLE is expected without any build-time errors.
Review URL: http://codereview.chromium.org/16554
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8126 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/waitable_event_watcher_unittest.cc')
-rw-r--r-- | base/waitable_event_watcher_unittest.cc | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/base/waitable_event_watcher_unittest.cc b/base/waitable_event_watcher_unittest.cc new file mode 100644 index 0000000..c50807f --- /dev/null +++ b/base/waitable_event_watcher_unittest.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2006-2008 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. + +#include "base/message_loop.h" +#include "base/platform_thread.h" +#include "base/waitable_event.h" +#include "base/waitable_event_watcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::WaitableEvent; +using base::WaitableEventWatcher; + +namespace { + +class QuitDelegate : public WaitableEventWatcher::Delegate { + public: + virtual void OnWaitableEventSignaled(WaitableEvent* event) { + MessageLoop::current()->Quit(); + } +}; + +class DecrementCountDelegate : public WaitableEventWatcher::Delegate { + public: + DecrementCountDelegate(int* counter) : counter_(counter) { + } + virtual void OnWaitableEventSignaled(WaitableEvent* object) { + --(*counter_); + } + private: + int* counter_; +}; + +} // namespace + +void RunTest_BasicSignal(MessageLoop::Type message_loop_type) { + MessageLoop message_loop(message_loop_type); + + // A manual-reset event that is not yet signaled. + WaitableEvent event(true, false); + + WaitableEventWatcher watcher; + EXPECT_EQ(NULL, watcher.GetWatchedObject()); + + QuitDelegate delegate; + watcher.StartWatching(&event, &delegate); + EXPECT_EQ(&event, watcher.GetWatchedObject()); + + event.Signal(); + + MessageLoop::current()->Run(); + + EXPECT_EQ(NULL, watcher.GetWatchedObject()); +} + +void RunTest_BasicCancel(MessageLoop::Type message_loop_type) { + MessageLoop message_loop(message_loop_type); + + // A manual-reset event that is not yet signaled. + WaitableEvent event(true, false); + + WaitableEventWatcher watcher; + + QuitDelegate delegate; + watcher.StartWatching(&event, &delegate); + + watcher.StopWatching(); +} + +void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) { + MessageLoop message_loop(message_loop_type); + + // A manual-reset event that is not yet signaled. + WaitableEvent event(true, false); + + WaitableEventWatcher watcher; + + int counter = 1; + DecrementCountDelegate delegate(&counter); + + watcher.StartWatching(&event, &delegate); + + event.Signal(); + + // Let the background thread do its business + PlatformThread::Sleep(30); + + watcher.StopWatching(); + + MessageLoop::current()->RunAllPending(); + + // Our delegate should not have fired. + EXPECT_EQ(1, counter); +} + +void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) { + // Simulate a MessageLoop that dies before an WaitableEventWatcher. This + // ordinarily doesn't happen when people use the Thread class, but it can + // happen when people use the Singleton pattern or atexit. + WaitableEvent event(true, false); + { + WaitableEventWatcher watcher; + { + MessageLoop message_loop(message_loop_type); + + QuitDelegate delegate; + watcher.StartWatching(&event, &delegate); + } + } +} + +//----------------------------------------------------------------------------- + +TEST(ObjectWatcherTest, BasicSignal) { + RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT); + RunTest_BasicSignal(MessageLoop::TYPE_IO); + RunTest_BasicSignal(MessageLoop::TYPE_UI); +} + +TEST(ObjectWatcherTest, BasicCancel) { + RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT); + RunTest_BasicCancel(MessageLoop::TYPE_IO); + RunTest_BasicCancel(MessageLoop::TYPE_UI); +} + +TEST(ObjectWatcherTest, CancelAfterSet) { + RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT); + RunTest_CancelAfterSet(MessageLoop::TYPE_IO); + RunTest_CancelAfterSet(MessageLoop::TYPE_UI); +} + +TEST(ObjectWatcherTest, OutlivesMessageLoop) { + RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT); + RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO); + RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI); +} |