ipc/chromium/src/base/object_watcher.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include "base/object_watcher.h"
     7 #include "base/logging.h"
     9 namespace base {
    11 //-----------------------------------------------------------------------------
    13 struct ObjectWatcher::Watch : public Task {
    14   ObjectWatcher* watcher;    // The associated ObjectWatcher instance
    15   HANDLE object;             // The object being watched
    16   HANDLE wait_object;        // Returned by RegisterWaitForSingleObject
    17   MessageLoop* origin_loop;  // Used to get back to the origin thread
    18   Delegate* delegate;        // Delegate to notify when signaled
    19   bool did_signal;           // DoneWaiting was called
    21   virtual void Run() {
    22     // The watcher may have already been torn down, in which case we need to
    23     // just get out of dodge.
    24     if (!watcher)
    25       return;
    27     DCHECK(did_signal);
    28     watcher->StopWatching();
    30     delegate->OnObjectSignaled(object);
    31   }
    32 };
    34 //-----------------------------------------------------------------------------
    36 ObjectWatcher::ObjectWatcher() : watch_(NULL) {
    37 }
    39 ObjectWatcher::~ObjectWatcher() {
    40   StopWatching();
    41 }
    43 bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {
    44   if (watch_) {
    45     NOTREACHED() << "Already watching an object";
    46     return false;
    47   }
    49   Watch* watch = new Watch;
    50   watch->watcher = this;
    51   watch->object = object;
    52   watch->origin_loop = MessageLoop::current();
    53   watch->delegate = delegate;
    54   watch->did_signal = false;
    56   // Since our job is to just notice when an object is signaled and report the
    57   // result back to this thread, we can just run on a Windows wait thread.
    58   DWORD wait_flags = WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE;
    60   if (!RegisterWaitForSingleObject(&watch->wait_object, object, DoneWaiting,
    61                                    watch, INFINITE, wait_flags)) {
    62     NOTREACHED() << "RegisterWaitForSingleObject failed: " << GetLastError();
    63     delete watch;
    64     return false;
    65   }
    67   watch_ = watch;
    69   // We need to know if the current message loop is going away so we can
    70   // prevent the wait thread from trying to access a dead message loop.
    71   MessageLoop::current()->AddDestructionObserver(this);
    72   return true;
    73 }
    75 bool ObjectWatcher::StopWatching() {
    76   if (!watch_)
    77     return false;
    79   // Make sure ObjectWatcher is used in a single-threaded fashion.
    80   DCHECK(watch_->origin_loop == MessageLoop::current());
    82   // If DoneWaiting is in progress, we wait for it to finish.  We know whether
    83   // DoneWaiting happened or not by inspecting the did_signal flag.
    84   if (!UnregisterWaitEx(watch_->wait_object, INVALID_HANDLE_VALUE)) {
    85     NOTREACHED() << "UnregisterWaitEx failed: " << GetLastError();
    86     return false;
    87   }
    89   // Make sure that we see any mutation to did_signal.  This should be a no-op
    90   // since we expect that UnregisterWaitEx resulted in a memory barrier, but
    91   // just to be sure, we're going to be explicit.
    92   MemoryBarrier();
    94   // If the watch has been posted, then we need to make sure it knows not to do
    95   // anything once it is run.
    96   watch_->watcher = NULL;
    98   // If DoneWaiting was called, then the watch would have been posted as a
    99   // task, and will therefore be deleted by the MessageLoop.  Otherwise, we
   100   // need to take care to delete it here.
   101   if (!watch_->did_signal)
   102     delete watch_;
   104   watch_ = NULL;
   106   MessageLoop::current()->RemoveDestructionObserver(this);
   107   return true;
   108 }
   110 HANDLE ObjectWatcher::GetWatchedObject() {
   111   if (!watch_)
   112     return NULL;
   114   return watch_->object;
   115 }
   117 // static
   118 void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) {
   119   DCHECK(!timed_out);
   121   Watch* watch = static_cast<Watch*>(param);
   123   // Record that we ran this function.
   124   watch->did_signal = true;
   126   // We rely on the locking in PostTask() to ensure that a memory barrier is
   127   // provided, which in turn ensures our change to did_signal can be observed
   128   // on the target thread.
   129   watch->origin_loop->PostTask(FROM_HERE, watch);
   130 }
   132 void ObjectWatcher::WillDestroyCurrentMessageLoop() {
   133   // Need to shutdown the watch so that we don't try to access the MessageLoop
   134   // after this point.
   135   StopWatching();
   136 }
   138 }  // namespace base

mercurial