Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ | 5 #ifndef MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ |
| 6 #define MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ | 6 #define MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ |
| 7 | 7 |
| 8 #include <map> | |
| 9 #include <memory> | |
| 10 | |
| 11 #include "mojo/edk/system/awakable.h" | |
| 8 #include "mojo/edk/system/dispatcher.h" | 12 #include "mojo/edk/system/dispatcher.h" |
| 13 #include "mojo/edk/util/ref_ptr.h" | |
| 14 #include "mojo/edk/util/thread_annotations.h" | |
| 9 #include "mojo/public/cpp/system/macros.h" | 15 #include "mojo/public/cpp/system/macros.h" |
| 10 | 16 |
| 11 namespace mojo { | 17 namespace mojo { |
| 12 namespace system { | 18 namespace system { |
| 13 | 19 |
| 14 // This is the |Dispatcher| implementation for wait sets (created by the Mojo | 20 // This is the |Dispatcher| implementation for wait sets (created by the Mojo |
| 15 // primitive |MojoCreateWaitSet()|). This class is thread-safe. | 21 // primitive |MojoCreateWaitSet()|). This class is thread-safe. |
| 16 class WaitSetDispatcher final : public Dispatcher { | 22 // TODO(vtl): We rely on |Dispatcher| itself never acquiring any other mutex |
| 23 // under |mutex()|. We should specify (and double-check) this requirement. | |
| 24 class WaitSetDispatcher final : public Dispatcher, public Awakable { | |
| 17 public: | 25 public: |
| 18 // The default/standard rights for a wait set handle. Note that they are not | 26 // The default/standard rights for a wait set handle. Note that they are not |
| 19 // transferrable. | 27 // transferrable. |
| 20 // TODO(vtl): Figure out if these are the correct rights. (E.g., we currently | 28 // TODO(vtl): Figure out if these are the correct rights. (E.g., we currently |
| 21 // don't have get/set options functions ... but maybe we should?) | 29 // don't have get/set options functions ... but maybe we should?) |
| 22 static constexpr MojoHandleRights kDefaultHandleRights = | 30 static constexpr MojoHandleRights kDefaultHandleRights = |
| 23 MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | | 31 MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | |
| 24 MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; | 32 MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; |
| 25 | 33 |
| 26 // The default options to use for |MojoCreateWaitSet()|. (Real uses should | 34 // The default options to use for |MojoCreateWaitSet()|. (Real uses should |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 45 static util::RefPtr<WaitSetDispatcher> Create( | 53 static util::RefPtr<WaitSetDispatcher> Create( |
| 46 const MojoCreateWaitSetOptions& /*validated_options*/) { | 54 const MojoCreateWaitSetOptions& /*validated_options*/) { |
| 47 return AdoptRef(new WaitSetDispatcher()); | 55 return AdoptRef(new WaitSetDispatcher()); |
| 48 } | 56 } |
| 49 | 57 |
| 50 // |Dispatcher| public methods: | 58 // |Dispatcher| public methods: |
| 51 Type GetType() const override; | 59 Type GetType() const override; |
| 52 bool SupportsEntrypointClass(EntrypointClass entrypoint_class) const override; | 60 bool SupportsEntrypointClass(EntrypointClass entrypoint_class) const override; |
| 53 | 61 |
| 54 private: | 62 private: |
| 63 // Represents an entry in the wait set. | |
| 64 struct Entry { | |
| 65 enum class TriggerState { | |
| 66 NOT_TRIGGERED, | |
| 67 POSSIBLY_SATISFIED, | |
| 68 NEVER_SATISFIABLE, | |
| 69 CLOSED | |
| 70 }; | |
| 71 | |
| 72 Entry(MojoHandleSignals signals, uint64_t cookie); | |
| 73 ~Entry(); | |
| 74 | |
| 75 const MojoHandleSignals signals; | |
| 76 const uint64_t cookie; | |
| 77 // There are two cases when |dispatcher| is null for an |Entry| in | |
| 78 // |WaitSetDispatcher::entries_|: | |
| 79 // - The wait set was closed in the middle of |WaitSetAddImpl()|; | |
| 80 // |entries_| will be cleared out on closing, but |WaitSetAddImpl()| | |
| 81 // must detect this and actually remove the dispatcher (which only it | |
| 82 // knows about) from the "target" dispatcher's awakable list. | |
| 83 // - It's an entry whose dispatcher was closed. | |
| 84 util::RefPtr<Dispatcher> dispatcher; | |
| 85 TriggerState trigger_state = TriggerState::NOT_TRIGGERED; | |
| 86 | |
| 87 // Only meaningful if |trigger_state| is not |TriggerState::NOT_TRIGGERED|. | |
| 88 // This is used to maintain a doubly linked list of entries that are | |
| 89 // possibly satisfied. |possibly_triggered_previous| and | |
| 90 // |possibly_triggered_next| are null if |this| is equal to | |
| 91 // |WaitSetDispatcher::possibly_triggered_head_| and | |
| 92 // |...::possibly_triggered_tail_|, respectively. | |
| 93 Entry* possibly_triggered_previous = nullptr; | |
| 94 Entry* possibly_triggered_next = nullptr; | |
| 95 }; | |
| 96 | |
| 55 WaitSetDispatcher(); | 97 WaitSetDispatcher(); |
| 56 ~WaitSetDispatcher() override; | 98 ~WaitSetDispatcher() override; |
| 57 | 99 |
| 58 // |Dispatcher| protected methods: | 100 // |Dispatcher| protected methods: |
| 101 void CloseImplNoLock() override; | |
| 59 util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock( | 102 util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock( |
| 60 MessagePipe* message_pipe, | 103 MessagePipe* message_pipe, |
| 61 unsigned port) override; | 104 unsigned port) override; |
| 62 MojoResult WaitSetAddImpl(UserPointer<const MojoWaitSetAddOptions> options, | 105 MojoResult WaitSetAddImpl(UserPointer<const MojoWaitSetAddOptions> options, |
| 63 Handle&& handle, | 106 util::RefPtr<Dispatcher>&& dispatcher, |
| 64 MojoHandleSignals signals, | 107 MojoHandleSignals signals, |
| 65 uint64_t cookie) override; | 108 uint64_t cookie) override; |
| 66 MojoResult WaitSetRemoveImpl(uint64_t cookie) override; | 109 MojoResult WaitSetRemoveImpl(uint64_t cookie) override; |
| 67 MojoResult WaitSetWaitImpl(MojoDeadline deadline, | 110 MojoResult WaitSetWaitImpl(MojoDeadline deadline, |
| 68 UserPointer<uint32_t> num_results, | 111 UserPointer<uint32_t> num_results, |
| 69 UserPointer<MojoWaitSetResult> results, | 112 UserPointer<MojoWaitSetResult> results, |
| 70 UserPointer<uint32_t> max_results) override; | 113 UserPointer<uint32_t> max_results) override; |
| 71 | 114 |
| 115 // |Awakable| implementation: | |
| 116 bool Awake(MojoResult result, uint64_t context) override; | |
| 117 | |
| 118 void AddPossiblyTriggeredNoLock(Entry* entry, | |
| 119 Entry::TriggerState new_trigger_state) | |
| 120 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); | |
| 121 void RemovePossiblyTriggeredNoLock(Entry* entry) | |
| 122 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); | |
| 123 | |
| 124 // Set when in the middle of a wait set operation (i.e., |WaitSet...Impl()|) | |
| 125 // with |mutex()| *unlocked*; if attempted (on a different thread), other wait | |
| 126 // set operations should report "busy". Note: Even if |is_busy_| is true, the | |
| 127 // wait set may still be closed. | |
| 128 bool is_busy_ MOJO_GUARDED_BY(mutex()) = false; | |
| 129 | |
| 130 // Map of cookies to entries. | |
| 131 using CookieToEntryMap = std::map<uint64_t, std::unique_ptr<Entry>>; | |
| 132 CookieToEntryMap entries_ MOJO_GUARDED_BY(mutex()); | |
| 133 | |
| 134 // Intrusive "doubly linked list" (via cookies) of entries that are possibly | |
| 135 // satisfied). | |
|
vardhan
2016/06/17 18:03:47
nit: remove ')'
also, feels unfortunate that you
| |
| 136 Entry* possibly_triggered_head_ MOJO_GUARDED_BY(mutex()) = nullptr; | |
| 137 Entry* possibly_triggered_tail_ MOJO_GUARDED_BY(mutex()) = nullptr; | |
| 138 // Size of the above list. | |
| 139 size_t possibly_triggered_count_ MOJO_GUARDED_BY(mutex()) = 0u; | |
| 140 | |
| 72 MOJO_DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher); | 141 MOJO_DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher); |
| 73 }; | 142 }; |
| 74 | 143 |
| 75 } // namespace system | 144 } // namespace system |
| 76 } // namespace mojo | 145 } // namespace mojo |
| 77 | 146 |
| 78 #endif // MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ | 147 #endif // MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ |
| OLD | NEW |