ipc/chromium/src/base/waitable_event.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/waitable_event.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,180 @@
     1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#ifndef BASE_WAITABLE_EVENT_H_
     1.9 +#define BASE_WAITABLE_EVENT_H_
    1.10 +
    1.11 +#include "base/basictypes.h"
    1.12 +
    1.13 +#if defined(OS_WIN)
    1.14 +#include <windows.h>
    1.15 +#endif
    1.16 +
    1.17 +#if defined(OS_POSIX)
    1.18 +#include <list>
    1.19 +#include <utility>
    1.20 +#include "base/condition_variable.h"
    1.21 +#include "base/lock.h"
    1.22 +#include "base/ref_counted.h"
    1.23 +#endif
    1.24 +
    1.25 +#include "base/message_loop.h"
    1.26 +
    1.27 +namespace base {
    1.28 +
    1.29 +// This replaces INFINITE from Win32
    1.30 +static const int kNoTimeout = -1;
    1.31 +
    1.32 +class TimeDelta;
    1.33 +
    1.34 +// A WaitableEvent can be a useful thread synchronization tool when you want to
    1.35 +// allow one thread to wait for another thread to finish some work. For
    1.36 +// non-Windows systems, this can only be used from within a single address
    1.37 +// space.
    1.38 +//
    1.39 +// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
    1.40 +// protect a simple boolean value.  However, if you find yourself using a
    1.41 +// WaitableEvent in conjunction with a Lock to wait for a more complex state
    1.42 +// change (e.g., for an item to be added to a queue), then you should probably
    1.43 +// be using a ConditionVariable instead of a WaitableEvent.
    1.44 +//
    1.45 +// NOTE: On Windows, this class provides a subset of the functionality afforded
    1.46 +// by a Windows event object.  This is intentional.  If you are writing Windows
    1.47 +// specific code and you need other features of a Windows event, then you might
    1.48 +// be better off just using an Windows event directly.
    1.49 +class WaitableEvent {
    1.50 + public:
    1.51 +  // If manual_reset is true, then to set the event state to non-signaled, a
    1.52 +  // consumer must call the Reset method.  If this parameter is false, then the
    1.53 +  // system automatically resets the event state to non-signaled after a single
    1.54 +  // waiting thread has been released.
    1.55 +  WaitableEvent(bool manual_reset, bool initially_signaled);
    1.56 +
    1.57 +#if defined(OS_WIN)
    1.58 +  // Create a WaitableEvent from an Event HANDLE which has already been
    1.59 +  // created. This objects takes ownership of the HANDLE and will close it when
    1.60 +  // deleted.
    1.61 +  explicit WaitableEvent(HANDLE event_handle);
    1.62 +
    1.63 +  // Releases ownership of the handle from this object.
    1.64 +  HANDLE Release();
    1.65 +#endif
    1.66 +
    1.67 +  ~WaitableEvent();
    1.68 +
    1.69 +  // Put the event in the un-signaled state.
    1.70 +  void Reset();
    1.71 +
    1.72 +  // Put the event in the signaled state.  Causing any thread blocked on Wait
    1.73 +  // to be woken up.
    1.74 +  void Signal();
    1.75 +
    1.76 +  // Returns true if the event is in the signaled state, else false.  If this
    1.77 +  // is not a manual reset event, then this test will cause a reset.
    1.78 +  bool IsSignaled();
    1.79 +
    1.80 +  // Wait indefinitely for the event to be signaled.  Returns true if the event
    1.81 +  // was signaled, else false is returned to indicate that waiting failed.
    1.82 +  bool Wait();
    1.83 +
    1.84 +  // Wait up until max_time has passed for the event to be signaled.  Returns
    1.85 +  // true if the event was signaled.  If this method returns false, then it
    1.86 +  // does not necessarily mean that max_time was exceeded.
    1.87 +  bool TimedWait(const TimeDelta& max_time);
    1.88 +
    1.89 +#if defined(OS_WIN)
    1.90 +  HANDLE handle() const { return handle_; }
    1.91 +#endif
    1.92 +
    1.93 +  // Wait, synchronously, on multiple events.
    1.94 +  //   waitables: an array of WaitableEvent pointers
    1.95 +  //   count: the number of elements in @waitables
    1.96 +  //
    1.97 +  // returns: the index of a WaitableEvent which has been signaled.
    1.98 +  //
    1.99 +  // You MUST NOT delete any of the WaitableEvent objects while this wait is
   1.100 +  // happening.
   1.101 +  static size_t WaitMany(WaitableEvent** waitables, size_t count);
   1.102 +
   1.103 +  // For asynchronous waiting, see WaitableEventWatcher
   1.104 +
   1.105 +  // This is a private helper class. It's here because it's used by friends of
   1.106 +  // this class (such as WaitableEventWatcher) to be able to enqueue elements
   1.107 +  // of the wait-list
   1.108 +  class Waiter {
   1.109 +   public:
   1.110 +    // Signal the waiter to wake up.
   1.111 +    //
   1.112 +    // Consider the case of a Waiter which is in multiple WaitableEvent's
   1.113 +    // wait-lists. Each WaitableEvent is automatic-reset and two of them are
   1.114 +    // signaled at the same time. Now, each will wake only the first waiter in
   1.115 +    // the wake-list before resetting. However, if those two waiters happen to
   1.116 +    // be the same object (as can happen if another thread didn't have a chance
   1.117 +    // to dequeue the waiter from the other wait-list in time), two auto-resets
   1.118 +    // will have happened, but only one waiter has been signaled!
   1.119 +    //
   1.120 +    // Because of this, a Waiter may "reject" a wake by returning false. In
   1.121 +    // this case, the auto-reset WaitableEvent shouldn't act as if anything has
   1.122 +    // been notified.
   1.123 +    virtual bool Fire(WaitableEvent* signaling_event) = 0;
   1.124 +
   1.125 +    // Waiters may implement this in order to provide an extra condition for
   1.126 +    // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
   1.127 +    // pointers match then this function is called as a final check. See the
   1.128 +    // comments in ~Handle for why.
   1.129 +    virtual bool Compare(void* tag) = 0;
   1.130 +  };
   1.131 +
   1.132 + private:
   1.133 +  friend class WaitableEventWatcher;
   1.134 +
   1.135 +#if defined(OS_WIN)
   1.136 +  HANDLE handle_;
   1.137 +#else
   1.138 +  // On Windows, one can close a HANDLE which is currently being waited on. The
   1.139 +  // MSDN documentation says that the resulting behaviour is 'undefined', but
   1.140 +  // it doesn't crash. However, if we were to include the following members
   1.141 +  // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an
   1.142 +  // event which gets deleted. This mismatch has bitten us several times now,
   1.143 +  // so we have a kernel of the WaitableEvent, which is reference counted.
   1.144 +  // WaitableEventWatchers may then take a reference and thus match the Windows
   1.145 +  // behaviour.
   1.146 +  struct WaitableEventKernel :
   1.147 +      public RefCountedThreadSafe<WaitableEventKernel> {
   1.148 +   public:
   1.149 +    WaitableEventKernel(bool manual_reset, bool initially_signaled)
   1.150 +        : manual_reset_(manual_reset),
   1.151 +          signaled_(initially_signaled) {
   1.152 +    }
   1.153 +
   1.154 +    bool Dequeue(Waiter* waiter, void* tag);
   1.155 +
   1.156 +    Lock lock_;
   1.157 +    const bool manual_reset_;
   1.158 +    bool signaled_;
   1.159 +    std::list<Waiter*> waiters_;
   1.160 +  };
   1.161 +
   1.162 +  scoped_refptr<WaitableEventKernel> kernel_;
   1.163 +
   1.164 +  bool SignalAll();
   1.165 +  bool SignalOne();
   1.166 +  void Enqueue(Waiter* waiter);
   1.167 +
   1.168 +  // When dealing with arrays of WaitableEvent*, we want to sort by the address
   1.169 +  // of the WaitableEvent in order to have a globally consistent locking order.
   1.170 +  // In that case we keep them, in sorted order, in an array of pairs where the
   1.171 +  // second element is the index of the WaitableEvent in the original,
   1.172 +  // unsorted, array.
   1.173 +  typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
   1.174 +  static size_t EnqueueMany(WaiterAndIndex* waitables,
   1.175 +                            size_t count, Waiter* waiter);
   1.176 +#endif
   1.177 +
   1.178 +  DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
   1.179 +};
   1.180 +
   1.181 +}  // namespace base
   1.182 +
   1.183 +#endif  // BASE_WAITABLE_EVENT_H_

mercurial