Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(604)

Unified Diff: mojo/edk/system/wait_set_dispatcher.h

Issue 2070523003: EDK: wait sets: Implement WaitSetDispatcher::WaitSet{AddRemove}Impl(). (Closed) Base URL: https://github.com/domokit/mojo.git@work796_wait_set_3.5
Patch Set: many fixes Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/edk/system/dispatcher.cc ('k') | mojo/edk/system/wait_set_dispatcher.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/edk/system/wait_set_dispatcher.h
diff --git a/mojo/edk/system/wait_set_dispatcher.h b/mojo/edk/system/wait_set_dispatcher.h
index 56e8654b9e54a65985c711ce81de1300346c80d5..0dadb04bd065afca07f863c1b54cf77fce668a97 100644
--- a/mojo/edk/system/wait_set_dispatcher.h
+++ b/mojo/edk/system/wait_set_dispatcher.h
@@ -5,7 +5,13 @@
#ifndef MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_
#define MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_
+#include <map>
+#include <memory>
+
+#include "mojo/edk/system/awakable.h"
#include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/util/ref_ptr.h"
+#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@@ -13,7 +19,9 @@ namespace system {
// This is the |Dispatcher| implementation for wait sets (created by the Mojo
// primitive |MojoCreateWaitSet()|). This class is thread-safe.
-class WaitSetDispatcher final : public Dispatcher {
+// TODO(vtl): We rely on |Dispatcher| itself never acquiring any other mutex
+// under |mutex()|. We should specify (and double-check) this requirement.
+class WaitSetDispatcher final : public Dispatcher, public Awakable {
public:
// The default/standard rights for a wait set handle. Note that they are not
// transferrable.
@@ -52,15 +60,50 @@ class WaitSetDispatcher final : public Dispatcher {
bool SupportsEntrypointClass(EntrypointClass entrypoint_class) const override;
private:
+ // Represents an entry in the wait set.
+ struct Entry {
+ enum class TriggerState {
+ NOT_TRIGGERED,
+ POSSIBLY_SATISFIED,
+ NEVER_SATISFIABLE,
+ CLOSED
+ };
+
+ Entry(MojoHandleSignals signals, uint64_t cookie);
+ ~Entry();
+
+ const MojoHandleSignals signals;
+ const uint64_t cookie;
+ // There are two cases when |dispatcher| is null for an |Entry| in
+ // |WaitSetDispatcher::entries_|:
+ // - The wait set was closed in the middle of |WaitSetAddImpl()|;
+ // |entries_| will be cleared out on closing, but |WaitSetAddImpl()|
+ // must detect this and actually remove the dispatcher (which only it
+ // knows about) from the "target" dispatcher's awakable list.
+ // - It's an entry whose dispatcher was closed.
+ util::RefPtr<Dispatcher> dispatcher;
+ TriggerState trigger_state = TriggerState::NOT_TRIGGERED;
+
+ // Only meaningful if |trigger_state| is not |TriggerState::NOT_TRIGGERED|.
+ // This is used to maintain a doubly linked list of entries that are
+ // possibly satisfied. |possibly_triggered_previous| and
+ // |possibly_triggered_next| are null if |this| is equal to
+ // |WaitSetDispatcher::possibly_triggered_head_| and
+ // |...::possibly_triggered_tail_|, respectively.
+ Entry* possibly_triggered_previous = nullptr;
+ Entry* possibly_triggered_next = nullptr;
+ };
+
WaitSetDispatcher();
~WaitSetDispatcher() override;
// |Dispatcher| protected methods:
+ void CloseImplNoLock() override;
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
MessagePipe* message_pipe,
unsigned port) override;
MojoResult WaitSetAddImpl(UserPointer<const MojoWaitSetAddOptions> options,
- Handle&& handle,
+ util::RefPtr<Dispatcher>&& dispatcher,
MojoHandleSignals signals,
uint64_t cookie) override;
MojoResult WaitSetRemoveImpl(uint64_t cookie) override;
@@ -69,6 +112,32 @@ class WaitSetDispatcher final : public Dispatcher {
UserPointer<MojoWaitSetResult> results,
UserPointer<uint32_t> max_results) override;
+ // |Awakable| implementation:
+ bool Awake(MojoResult result, uint64_t context) override;
+
+ void AddPossiblyTriggeredNoLock(Entry* entry,
+ Entry::TriggerState new_trigger_state)
+ MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex());
+ void RemovePossiblyTriggeredNoLock(Entry* entry)
+ MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex());
+
+ // Set when in the middle of a wait set operation (i.e., |WaitSet...Impl()|)
+ // with |mutex()| *unlocked*; if attempted (on a different thread), other wait
+ // set operations should report "busy". Note: Even if |is_busy_| is true, the
+ // wait set may still be closed.
+ bool is_busy_ MOJO_GUARDED_BY(mutex()) = false;
+
+ // Map of cookies to entries.
+ using CookieToEntryMap = std::map<uint64_t, std::unique_ptr<Entry>>;
+ CookieToEntryMap entries_ MOJO_GUARDED_BY(mutex());
+
+ // Intrusive "doubly linked list" (via cookies) of entries that are possibly
+ // satisfied).
vardhan 2016/06/17 18:03:47 nit: remove ')' also, feels unfortunate that you
+ Entry* possibly_triggered_head_ MOJO_GUARDED_BY(mutex()) = nullptr;
+ Entry* possibly_triggered_tail_ MOJO_GUARDED_BY(mutex()) = nullptr;
+ // Size of the above list.
+ size_t possibly_triggered_count_ MOJO_GUARDED_BY(mutex()) = 0u;
+
MOJO_DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher);
};
« no previous file with comments | « mojo/edk/system/dispatcher.cc ('k') | mojo/edk/system/wait_set_dispatcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698