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