LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - waitable_event.h (source / functions) Found Hit Coverage
Test: app.info Lines: 5 5 100.0 %
Date: 2012-06-02 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.7