summaryrefslogtreecommitdiffstats
path: root/base/object_watcher.cc
diff options
context:
space:
mode:
authordarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-09 08:11:26 +0000
committerdarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-09 08:11:26 +0000
commit12ec562ec0236a94fcb7b376aab7d13b83a3de8a (patch)
tree0cfe7c2682695d85eb0b456f8947366015d72f61 /base/object_watcher.cc
parent961501153a1f85acc07321c1a15ff31352faa2c4 (diff)
downloadchromium_src-12ec562ec0236a94fcb7b376aab7d13b83a3de8a.zip
chromium_src-12ec562ec0236a94fcb7b376aab7d13b83a3de8a.tar.gz
chromium_src-12ec562ec0236a94fcb7b376aab7d13b83a3de8a.tar.bz2
experiment with APCs
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@629 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/object_watcher.cc')
-rw-r--r--base/object_watcher.cc44
1 files changed, 33 insertions, 11 deletions
diff --git a/base/object_watcher.cc b/base/object_watcher.cc
index bb4b568..bc5cdd2 100644
--- a/base/object_watcher.cc
+++ b/base/object_watcher.cc
@@ -29,21 +29,26 @@
#include "base/object_watcher.h"
+#include "base/histogram.h"
#include "base/logging.h"
namespace base {
+static int live_watches = 0;
+
//-----------------------------------------------------------------------------
-struct ObjectWatcher::Watch : public Task {
+struct ObjectWatcher::Watch {
ObjectWatcher* watcher; // The associated ObjectWatcher instance
HANDLE object; // The object being watched
HANDLE wait_object; // Returned by RegisterWaitForSingleObject
- MessageLoop* origin_loop; // Used to get back to the origin thread
+ HANDLE origin_thread;
Delegate* delegate; // Delegate to notify when signaled
bool did_signal; // DoneWaiting was called
- virtual void Run() {
+ TimeTicks signal_time;
+
+ void Run() {
// The watcher may have already been torn down, in which case we need to
// just get out of dodge.
if (!watcher)
@@ -52,8 +57,21 @@ struct ObjectWatcher::Watch : public Task {
DCHECK(did_signal);
watcher->StopWatching();
+ TimeDelta delta = TimeTicks::Now() - signal_time;
+ HISTOGRAM_TIMES(L"ObjectWatcher_CallbackLatency", delta);
+
delegate->OnObjectSignaled(object);
}
+
+ ~Watch() {
+ CloseHandle(origin_thread);
+ }
+
+ static void CALLBACK ReturnToOriginThread(ULONG_PTR param) {
+ Watch* self = reinterpret_cast<Watch*>(param);
+ self->Run();
+ delete self;
+ }
};
//-----------------------------------------------------------------------------
@@ -74,10 +92,12 @@ bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {
Watch* watch = new Watch;
watch->watcher = this;
watch->object = object;
- watch->origin_loop = MessageLoop::current();
watch->delegate = delegate;
watch->did_signal = false;
+ watch->origin_thread =
+ OpenThread(THREAD_SET_CONTEXT, FALSE, GetCurrentThreadId());
+
// Since our job is to just notice when an object is signaled and report the
// result back to this thread, we can just run on a Windows wait thread.
DWORD wait_flags = WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE;
@@ -91,6 +111,9 @@ bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {
watch_ = watch;
+ ++live_watches;
+ HISTOGRAM_COUNTS(L"ObjectWatcher_LiveWatches", live_watches);
+
// We need to know if the current message loop is going away so we can
// prevent the wait thread from trying to access a dead message loop.
MessageLoop::current()->AddDestructionObserver(this);
@@ -101,8 +124,10 @@ bool ObjectWatcher::StopWatching() {
if (!watch_)
return false;
+ --live_watches;
+
// Make sure ObjectWatcher is used in a single-threaded fashion.
- DCHECK(watch_->origin_loop == MessageLoop::current());
+ DCHECK(GetThreadId(watch_->origin_thread) == GetCurrentThreadId());
// If DoneWaiting is in progress, we wait for it to finish. We know whether
// DoneWaiting happened or not by inspecting the did_signal flag.
@@ -141,13 +166,10 @@ void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) {
// Record that we ran this function.
watch->did_signal = true;
- // TODO(darin): This is just a test.
- watch->set_priority(1000);
+ watch->signal_time = TimeTicks::Now();
- // We rely on the locking in PostTask() to ensure that a memory barrier is
- // provided, which in turn ensures our change to did_signal can be observed
- // on the target thread.
- watch->origin_loop->PostTask(FROM_HERE, watch);
+ QueueUserAPC(Watch::ReturnToOriginThread, watch->origin_thread,
+ reinterpret_cast<ULONG_PTR>(watch));
}
void ObjectWatcher::WillDestroyCurrentMessageLoop() {