• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_
6 #define MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include "base/macros.h"
12 #include "base/memory/ref_counted.h"
13 #include "mojo/public/c/system/trap.h"
14 #include "mojo/public/c/system/types.h"
15 #include "mojo/public/cpp/system/handle.h"
16 #include "mojo/public/cpp/system/system_export.h"
17 
18 namespace base {
19 class WaitableEvent;
20 }
21 
22 namespace mojo {
23 
24 // WaitSet provides an efficient means of blocking a sequence on any number of
25 // events and Mojo handle state changes.
26 //
27 // Unlike WaitMany(), which incurs some extra setup cost for every call, a
28 // WaitSet maintains some persistent accounting of the handles added or removed
29 // from the set. A blocking wait operation (see  the Wait() method  below) can
30 // then be performed multiple times for the same set of events and handles with
31 // minimal additional setup per call.
32 //
33 // WaitSet is NOT thread-safe, so naturally handles and events may not be added
34 // to or removed from the set while waiting.
35 class MOJO_CPP_SYSTEM_EXPORT WaitSet {
36  public:
37   WaitSet();
38   ~WaitSet();
39 
40   // Adds |event| to the set of events to wait on. If successful, any future
41   // Wait() on this WaitSet will wake up if the event is signaled.
42   //
43   // |event| is not owned.
44   //
45   // Return values:
46   //   |MOJO_RESULT_OK| if |event| has been successfully added.
47   //   |MOJO_RESULT_ALREADY_EXISTS| if |event| is already in this WaitSet.
48   MojoResult AddEvent(base::WaitableEvent* event);
49 
50   // Removes |event| from the set of events to wait on.
51   //
52   // Return values:
53   //   |MOJO_RESULT_OK| if |event| has been successfully added.
54   //   |MOJO_RESULT_NOT_FOUND| if |event| was not in the set.
55   MojoResult RemoveEvent(base::WaitableEvent* event);
56 
57   // Adds |handle| to the set of handles to wait on. If successful, any future
58   // Wait() on this WaitSet will wake up in the event that one or more signals
59   // in |signals| becomes satisfied on |handle| or all of them become
60   // permanently unsatisfiable.
61   //
62   // Return values:
63   //   |MOJO_RESULT_OK| if |handle| has been successfully added.
64   //   |MOJO_RESULT_ALREADY_EXISTS| if |handle| is already in this WaitSet.
65   //   |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle.
66   MojoResult AddHandle(Handle handle, MojoHandleSignals signals);
67 
68   // Removes |handle| from the set of handles to wait on. Future calls to
69   // Wait() will be unaffected by the state of this handle.
70   //
71   // Return values:
72   //   |MOJO_RESULT_OK| if |handle| has been successfully removed.
73   //   |MOJO_RESULT_NOT_FOUND| if |handle| was not in the set.
74   MojoResult RemoveHandle(Handle handle);
75 
76   // Waits on the current set of handles, waking up when one more of them meets
77   // the signaling conditions which were specified when they were added via
78   // AddHandle() above.
79   //
80   // |*num_ready_handles| on input must specify the number of entries available
81   // for output storage in |ready_handles| and |ready_result| (which must both
82   // be non-null). If |signals_states| is non-null it must also point to enough
83   // storage for |*num_ready_handles| MojoHandleSignalsState structures.
84   //
85   // Upon return, |*num_ready_handles| will contain the total number of handles
86   // whose information is stored in the given output buffers.
87   //
88   // If |ready_event| is non-null and the Wait() was unblocked by a user event
89   // signaling, the address of the event which signaled will be placed in
90   // |*ready_event|. Note that this is not necessarily exclusive to one or more
91   // handles also being ready. If |ready_event| is non-null and no user event
92   // was signaled for this Wait(), |*ready_event| will be null upon return.
93   //
94   // Every entry in |ready_handles| on output corresponds to one of the handles
95   // whose signaling state termianted the Wait() operation. Every corresponding
96   // entry in |ready_results| indicates the status of a ready handle according
97   // to the following result codes:
98   //   |MOJO_RESULT_OK| one or more signals for the handle has been satisfied.
99   //   |MOJO_RESULT_FAILED_PRECONDITION| all of the signals for the handle have
100   //       become permanently unsatisfiable.
101   //   |MOJO_RESULT_CANCELLED| if the handle has been closed from another
102   //       sequence. NOTE: It is important to recognize that this means the
103   //       corresponding value in |ready_handles| is either invalid, or valid
104   //       but referring to a different handle (i.e. has already been reused) by
105   //       the time Wait() returns. The handle in question is automatically
106   //       removed from the WaitSet.
107   void Wait(base::WaitableEvent** ready_event,
108             size_t* num_ready_handles,
109             Handle* ready_handles,
110             MojoResult* ready_results,
111             MojoHandleSignalsState* signals_states = nullptr);
112 
113  private:
114   class State;
115 
116   // Thread-safe state associated with this WaitSet. Used to aggregate
117   // notifications from watched handles.
118   scoped_refptr<State> state_;
119 
120   DISALLOW_COPY_AND_ASSIGN(WaitSet);
121 };
122 
123 }  // namespace mojo
124 
125 #endif  // MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_
126