// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_ #define MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_ #include <stddef.h> #include <stdint.h> #include "base/macros.h" #include "base/memory/ref_counted.h" #include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/system_export.h" namespace base { class WaitableEvent; } namespace mojo { // WaitSet provides an efficient means of blocking a sequence on any number of // events and Mojo handle state changes. // // Unlike WaitMany(), which incurs some extra setup cost for every call, a // WaitSet maintains some persistent accounting of the handles added or removed // from the set. A blocking wait operation (see the Wait() method below) can // then be performed multiple times for the same set of events and handles with // minimal additional setup per call. // // WaitSet is NOT thread-safe, so naturally handles and events may not be added // to or removed from the set while waiting. class MOJO_CPP_SYSTEM_EXPORT WaitSet { public: WaitSet(); ~WaitSet(); // Adds |event| to the set of events to wait on. If successful, any future // Wait() on this WaitSet will wake up if the event is signaled. // // |event| is not owned. // // Return values: // |MOJO_RESULT_OK| if |event| has been successfully added. // |MOJO_RESULT_ALREADY_EXISTS| if |event| is already in this WaitSet. MojoResult AddEvent(base::WaitableEvent* event); // Removes |event| from the set of events to wait on. // // Return values: // |MOJO_RESULT_OK| if |event| has been successfully added. // |MOJO_RESULT_NOT_FOUND| if |event| was not in the set. MojoResult RemoveEvent(base::WaitableEvent* event); // Adds |handle| to the set of handles to wait on. If successful, any future // Wait() on this WaitSet will wake up in the event that one or more signals // in |signals| becomes satisfied on |handle| or all of them become // permanently unsatisfiable. // // Return values: // |MOJO_RESULT_OK| if |handle| has been successfully added. // |MOJO_RESULT_ALREADY_EXISTS| if |handle| is already in this WaitSet. // |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle. MojoResult AddHandle(Handle handle, MojoHandleSignals signals); // Removes |handle| from the set of handles to wait on. Future calls to // Wait() will be unaffected by the state of this handle. // // Return values: // |MOJO_RESULT_OK| if |handle| has been successfully removed. // |MOJO_RESULT_NOT_FOUND| if |handle| was not in the set. MojoResult RemoveHandle(Handle handle); // Waits on the current set of handles, waking up when one more of them meets // the signaling conditions which were specified when they were added via // AddHandle() above. // // |*num_ready_handles| on input must specify the number of entries available // for output storage in |ready_handles| and |ready_result| (which must both // be non-null). If |signals_states| is non-null it must also point to enough // storage for |*num_ready_handles| MojoHandleSignalsState structures. // // Upon return, |*num_ready_handles| will contain the total number of handles // whose information is stored in the given output buffers. // // If |ready_event| is non-null and the Wait() was unblocked by a user event // signaling, the address of the event which signaled will be placed in // |*ready_event|. Note that this is not necessarily exclusive to one or more // handles also being ready. If |ready_event| is non-null and no user event // was signaled for this Wait(), |*ready_event| will be null upon return. // // Every entry in |ready_handles| on output corresponds to one of the handles // whose signaling state termianted the Wait() operation. Every corresponding // entry in |ready_results| indicates the status of a ready handle according // to the following result codes: // |MOJO_RESULT_OK| one or more signals for the handle has been satisfied. // |MOJO_RESULT_FAILED_PRECONDITION| all of the signals for the handle have // become permanently unsatisfiable. // |MOJO_RESULT_CANCELLED| if the handle has been closed from another // sequence. NOTE: It is important to recognize that this means the // corresponding value in |ready_handles| is either invalid, or valid // but referring to a different handle (i.e. has already been reused) by // the time Wait() returns. The handle in question is automatically // removed from the WaitSet. void Wait(base::WaitableEvent** ready_event, size_t* num_ready_handles, Handle* ready_handles, MojoResult* ready_results, MojoHandleSignalsState* signals_states = nullptr); private: class State; // Thread-safe state associated with this WaitSet. Used to aggregate // notifications from watched handles. scoped_refptr<State> state_; DISALLOW_COPY_AND_ASSIGN(WaitSet); }; } // namespace mojo #endif // MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_