LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - waitable_event.h (source / functions) Hit Total Coverage
Test: output.info Lines: 7 7 100.0 %
Date: 2017-07-14 16:53:18 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #ifndef BASE_WAITABLE_EVENT_H_
       8             : #define BASE_WAITABLE_EVENT_H_
       9             : 
      10             : #include "base/basictypes.h"
      11             : 
      12             : #if defined(OS_WIN)
      13             : #include <windows.h>
      14             : #endif
      15             : 
      16             : #if defined(OS_POSIX)
      17             : #include <list>
      18             : #include <utility>
      19             : #include "base/condition_variable.h"
      20             : #include "base/lock.h"
      21             : #include "nsISupportsImpl.h"
      22             : #include "nsAutoPtr.h"
      23             : #endif
      24             : 
      25             : #include "base/message_loop.h"
      26             : 
      27             : namespace base {
      28             : 
      29             : // This replaces INFINITE from Win32
      30             : static const int kNoTimeout = -1;
      31             : 
      32             : class TimeDelta;
      33             : 
      34             : // A WaitableEvent can be a useful thread synchronization tool when you want to
      35             : // allow one thread to wait for another thread to finish some work. For
      36             : // non-Windows systems, this can only be used from within a single address
      37             : // space.
      38             : //
      39             : // Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
      40             : // protect a simple boolean value.  However, if you find yourself using a
      41             : // WaitableEvent in conjunction with a Lock to wait for a more complex state
      42             : // change (e.g., for an item to be added to a queue), then you should probably
      43             : // be using a ConditionVariable instead of a WaitableEvent.
      44             : //
      45             : // NOTE: On Windows, this class provides a subset of the functionality afforded
      46             : // by a Windows event object.  This is intentional.  If you are writing Windows
      47             : // specific code and you need other features of a Windows event, then you might
      48             : // be better off just using an Windows event directly.
      49             : class WaitableEvent {
      50             :  public:
      51             :   // If manual_reset is true, then to set the event state to non-signaled, a
      52             :   // consumer must call the Reset method.  If this parameter is false, then the
      53             :   // system automatically resets the event state to non-signaled after a single
      54             :   // waiting thread has been released.
      55             :   WaitableEvent(bool manual_reset, bool initially_signaled);
      56             : 
      57             :   ~WaitableEvent();
      58             : 
      59             :   // Put the event in the un-signaled state.
      60             :   void Reset();
      61             : 
      62             :   // Put the event in the signaled state.  Causing any thread blocked on Wait
      63             :   // to be woken up.
      64             :   void Signal();
      65             : 
      66             :   // Returns true if the event is in the signaled state, else false.  If this
      67             :   // is not a manual reset event, then this test will cause a reset.
      68             :   bool IsSignaled();
      69             : 
      70             :   // Wait indefinitely for the event to be signaled.  Returns true if the event
      71             :   // was signaled, else false is returned to indicate that waiting failed.
      72             :   bool Wait();
      73             : 
      74             :   // Wait up until max_time has passed for the event to be signaled.  Returns
      75             :   // true if the event was signaled.  If this method returns false, then it
      76             :   // does not necessarily mean that max_time was exceeded.
      77             :   bool TimedWait(const TimeDelta& max_time);
      78             : 
      79             : #if defined(OS_WIN)
      80             :   HANDLE handle() const { return handle_; }
      81             : #endif
      82             : 
      83             :   // Wait, synchronously, on multiple events.
      84             :   //   waitables: an array of WaitableEvent pointers
      85             :   //   count: the number of elements in @waitables
      86             :   //
      87             :   // returns: the index of a WaitableEvent which has been signaled.
      88             :   //
      89             :   // You MUST NOT delete any of the WaitableEvent objects while this wait is
      90             :   // happening.
      91             :   static size_t WaitMany(WaitableEvent** waitables, size_t count);
      92             : 
      93             :   // For asynchronous waiting, see WaitableEventWatcher
      94             : 
      95             :   // This is a private helper class. It's here because it's used by friends of
      96             :   // this class (such as WaitableEventWatcher) to be able to enqueue elements
      97             :   // of the wait-list
      98         777 :   class Waiter {
      99             :    public:
     100             :     // Signal the waiter to wake up.
     101             :     //
     102             :     // Consider the case of a Waiter which is in multiple WaitableEvent's
     103             :     // wait-lists. Each WaitableEvent is automatic-reset and two of them are
     104             :     // signaled at the same time. Now, each will wake only the first waiter in
     105             :     // the wake-list before resetting. However, if those two waiters happen to
     106             :     // be the same object (as can happen if another thread didn't have a chance
     107             :     // to dequeue the waiter from the other wait-list in time), two auto-resets
     108             :     // will have happened, but only one waiter has been signaled!
     109             :     //
     110             :     // Because of this, a Waiter may "reject" a wake by returning false. In
     111             :     // this case, the auto-reset WaitableEvent shouldn't act as if anything has
     112             :     // been notified.
     113             :     virtual bool Fire(WaitableEvent* signaling_event) = 0;
     114             : 
     115             :     // Waiters may implement this in order to provide an extra condition for
     116             :     // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
     117             :     // pointers match then this function is called as a final check. See the
     118             :     // comments in ~Handle for why.
     119             :     virtual bool Compare(void* tag) = 0;
     120             :   };
     121             : 
     122             :  private:
     123             :   friend class WaitableEventWatcher;
     124             : 
     125             : #if defined(OS_WIN)
     126             :   HANDLE handle_;
     127             : #else
     128             :   // On Windows, one can close a HANDLE which is currently being waited on. The
     129             :   // MSDN documentation says that the resulting behaviour is 'undefined', but
     130             :   // it doesn't crash. However, if we were to include the following members
     131             :   // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an
     132             :   // event which gets deleted. This mismatch has bitten us several times now,
     133             :   // so we have a kernel of the WaitableEvent, which is reference counted.
     134             :   // WaitableEventWatchers may then take a reference and thus match the Windows
     135             :   // behaviour.
     136             :   struct WaitableEventKernel final {
     137             :    public:
     138          90 :     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WaitableEventKernel)
     139          72 :     WaitableEventKernel(bool manual_reset, bool initially_signaled)
     140          72 :         : manual_reset_(manual_reset),
     141          72 :           signaled_(initially_signaled) {
     142          72 :     }
     143             : 
     144             :     bool Dequeue(Waiter* waiter, void* tag);
     145             : 
     146             :     Lock lock_;
     147             :     const bool manual_reset_;
     148             :     bool signaled_;
     149             :     std::list<Waiter*> waiters_;
     150             :    protected:
     151           9 :     ~WaitableEventKernel() {}
     152             :   };
     153             : 
     154             :   RefPtr<WaitableEventKernel> kernel_;
     155             : 
     156             :   bool SignalAll();
     157             :   bool SignalOne();
     158             :   void Enqueue(Waiter* waiter);
     159             : 
     160             :   // When dealing with arrays of WaitableEvent*, we want to sort by the address
     161             :   // of the WaitableEvent in order to have a globally consistent locking order.
     162             :   // In that case we keep them, in sorted order, in an array of pairs where the
     163             :   // second element is the index of the WaitableEvent in the original,
     164             :   // unsorted, array.
     165             :   typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
     166             :   static size_t EnqueueMany(WaiterAndIndex* waitables,
     167             :                             size_t count, Waiter* waiter);
     168             : #endif
     169             : 
     170             :   DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
     171             : };
     172             : 
     173             : }  // namespace base
     174             : 
     175             : #endif  // BASE_WAITABLE_EVENT_H_

Generated by: LCOV version 1.13