Home | History | Annotate | Download | only in synchronization
      1 // Copyright (c) 2011 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.
      4 
      5 #ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_
      6 #define BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_
      7 #pragma once
      8 
      9 #include "build/build_config.h"
     10 
     11 #if defined(OS_WIN)
     12 #include "base/win/object_watcher.h"
     13 #else
     14 #include "base/message_loop.h"
     15 #include "base/synchronization/waitable_event.h"
     16 #endif
     17 
     18 #include "base/base_api.h"
     19 
     20 namespace base {
     21 
     22 class Flag;
     23 class AsyncWaiter;
     24 class AsyncCallbackTask;
     25 class WaitableEvent;
     26 
     27 // -----------------------------------------------------------------------------
     28 // This class provides a way to wait on a WaitableEvent asynchronously.
     29 //
     30 // Each instance of this object can be waiting on a single WaitableEvent. When
     31 // the waitable event is signaled, a callback is made in the thread of a given
     32 // MessageLoop. This callback can be deleted by deleting the waiter.
     33 //
     34 // Typical usage:
     35 //
     36 //   class MyClass : public base::WaitableEventWatcher::Delegate {
     37 //    public:
     38 //     void DoStuffWhenSignaled(WaitableEvent *waitable_event) {
     39 //       watcher_.StartWatching(waitable_event, this);
     40 //     }
     41 //     virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) {
     42 //       // OK, time to do stuff!
     43 //     }
     44 //    private:
     45 //     base::WaitableEventWatcher watcher_;
     46 //   };
     47 //
     48 // In the above example, MyClass wants to "do stuff" when waitable_event
     49 // becomes signaled. WaitableEventWatcher makes this task easy. When MyClass
     50 // goes out of scope, the watcher_ will be destroyed, and there is no need to
     51 // worry about OnWaitableEventSignaled being called on a deleted MyClass
     52 // pointer.
     53 //
     54 // BEWARE: With automatically reset WaitableEvents, a signal may be lost if it
     55 // occurs just before a WaitableEventWatcher is deleted. There is currently no
     56 // safe way to stop watching an automatic reset WaitableEvent without possibly
     57 // missing a signal.
     58 //
     59 // NOTE: you /are/ allowed to delete the WaitableEvent while still waiting on
     60 // it with a Watcher. It will act as if the event was never signaled.
     61 // -----------------------------------------------------------------------------
     62 
     63 class BASE_API WaitableEventWatcher
     64 #if defined(OS_POSIX)
     65     : public MessageLoop::DestructionObserver
     66 #endif
     67 {
     68  public:
     69 
     70   WaitableEventWatcher();
     71   ~WaitableEventWatcher();
     72 
     73   class Delegate {
     74    public:
     75     virtual ~Delegate() { }
     76 
     77     // -------------------------------------------------------------------------
     78     // This is called on the MessageLoop thread when WaitableEvent has been
     79     // signaled.
     80     //
     81     // Note: the event may not be signaled by the time that this function is
     82     // called. This indicates only that it has been signaled at some point in
     83     // the past.
     84     // -------------------------------------------------------------------------
     85     virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) = 0;
     86   };
     87 
     88   // ---------------------------------------------------------------------------
     89   // When @event is signaled, the given delegate is called on the thread of the
     90   // current message loop when StartWatching is called. The delegate is not
     91   // deleted.
     92   // ---------------------------------------------------------------------------
     93   bool StartWatching(WaitableEvent* event, Delegate* delegate);
     94 
     95   // ---------------------------------------------------------------------------
     96   // Cancel the current watch. Must be called from the same thread which
     97   // started the watch.
     98   //
     99   // Does nothing if no event is being watched, nor if the watch has completed.
    100   // The delegate will *not* be called for the current watch after this
    101   // function returns. Since the delegate runs on the same thread as this
    102   // function, it cannot be called during this function either.
    103   // ---------------------------------------------------------------------------
    104   void StopWatching();
    105 
    106   // ---------------------------------------------------------------------------
    107   // Return the currently watched event, or NULL if no object is currently being
    108   // watched.
    109   // ---------------------------------------------------------------------------
    110   WaitableEvent* GetWatchedEvent();
    111 
    112   // ---------------------------------------------------------------------------
    113   // Return the delegate, or NULL if there is no delegate.
    114   // ---------------------------------------------------------------------------
    115   Delegate* delegate() {
    116     return delegate_;
    117   }
    118 
    119  private:
    120 #if defined(OS_WIN)
    121   // ---------------------------------------------------------------------------
    122   // The helper class exists because, if WaitableEventWatcher were to inherit
    123   // from ObjectWatcher::Delegate, then it couldn't also have an inner class
    124   // called Delegate (at least on Windows). Thus this object exists to proxy
    125   // the callback function
    126   // ---------------------------------------------------------------------------
    127   class ObjectWatcherHelper : public win::ObjectWatcher::Delegate {
    128    public:
    129     ObjectWatcherHelper(WaitableEventWatcher* watcher);
    130 
    131     // -------------------------------------------------------------------------
    132     // Implementation of ObjectWatcher::Delegate
    133     // -------------------------------------------------------------------------
    134     void OnObjectSignaled(HANDLE h);
    135 
    136    private:
    137     WaitableEventWatcher *const watcher_;
    138   };
    139 
    140   void OnObjectSignaled();
    141 
    142   ObjectWatcherHelper helper_;
    143   win::ObjectWatcher watcher_;
    144 #else
    145   // ---------------------------------------------------------------------------
    146   // Implementation of MessageLoop::DestructionObserver
    147   // ---------------------------------------------------------------------------
    148   virtual void WillDestroyCurrentMessageLoop();
    149 
    150   MessageLoop* message_loop_;
    151   scoped_refptr<Flag> cancel_flag_;
    152   AsyncWaiter* waiter_;
    153   AsyncCallbackTask* callback_task_;
    154   scoped_refptr<WaitableEvent::WaitableEventKernel> kernel_;
    155 #endif
    156 
    157   WaitableEvent* event_;
    158 
    159   Delegate* delegate_;
    160 };
    161 
    162 }  // namespace base
    163 
    164 #endif  // BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_
    165