| 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> | 8 #include <map> |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 return AdoptRef(new WaitSetDispatcher()); | 55 return AdoptRef(new WaitSetDispatcher()); |
| 56 } | 56 } |
| 57 | 57 |
| 58 // |Dispatcher| public methods: | 58 // |Dispatcher| public methods: |
| 59 Type GetType() const override; | 59 Type GetType() const override; |
| 60 bool SupportsEntrypointClass(EntrypointClass entrypoint_class) const override; | 60 bool SupportsEntrypointClass(EntrypointClass entrypoint_class) const override; |
| 61 | 61 |
| 62 private: | 62 private: |
| 63 // Represents an entry in the wait set. | 63 // Represents an entry in the wait set. |
| 64 struct Entry { | 64 struct Entry { |
| 65 enum class TriggerState { NOT_TRIGGERED, SATISFIED, UNSATISFIABLE, CLOSED }; | 65 Entry(util::RefPtr<Dispatcher>&& dispatcher, |
| 66 | 66 MojoHandleSignals signals, |
| 67 Entry(MojoHandleSignals signals, uint64_t cookie); | 67 uint64_t cookie); |
| 68 ~Entry(); | 68 ~Entry(); |
| 69 | 69 |
| 70 // |dispatcher| is only null for an |Entry| in |WaitSetDispatcher::entries_| |
| 71 // if the dispatcher was closed. |
| 72 util::RefPtr<Dispatcher> dispatcher; |
| 70 const MojoHandleSignals signals; | 73 const MojoHandleSignals signals; |
| 71 const uint64_t cookie; | 74 const uint64_t cookie; |
| 72 // There are two cases when |dispatcher| is null for an |Entry| in | |
| 73 // |WaitSetDispatcher::entries_|: | |
| 74 // - The wait set was closed in the middle of |WaitSetAddImpl()|; | |
| 75 // |entries_| will be cleared out on closing, but |WaitSetAddImpl()| | |
| 76 // must detect this and actually remove the dispatcher (which only it | |
| 77 // knows about) from the "target" dispatcher's awakable list. | |
| 78 // - It's an entry whose dispatcher was closed. | |
| 79 util::RefPtr<Dispatcher> dispatcher; | |
| 80 TriggerState trigger_state = TriggerState::NOT_TRIGGERED; | |
| 81 | 75 |
| 82 // Only meaningful if |trigger_state| is not |TriggerState::NOT_TRIGGERED|. | 76 // This is false until |WaitSetDispatcher::WaitSetAddImpl()| is "finished" |
| 83 // This is used to maintain a doubly linked list of entries that are | 77 // adding it. |...::WaitSetRemoveImpl()| won't acknowledge the existence of |
| 84 // possibly satisfied. |possibly_triggered_previous| and | 78 // this entry until this is true. |
| 85 // |possibly_triggered_next| are null if |this| is equal to | 79 bool ready = false; |
| 86 // |WaitSetDispatcher::possibly_triggered_head_| and | 80 |
| 87 // |...::possibly_triggered_tail_|, respectively. | 81 HandleSignalsState signals_state; |
| 88 Entry* possibly_triggered_previous = nullptr; | 82 bool is_triggered = false; |
| 89 Entry* possibly_triggered_next = nullptr; | 83 |
| 84 // Only meaningful if |is_triggered| is true. This is used to maintain a |
| 85 // doubly linked list of entries that are triggered (for various reasons: |
| 86 // being satisfied, being never-satisfiable, being cancelled/closed). |
| 87 // |triggered_previous| and |triggered_next| are null if |this| is equal to |
| 88 // |WaitSetDispatcher::triggered_head_| and |
| 89 // |WaitSetDispatcher::triggered_tail_|, respectively. |
| 90 Entry* triggered_previous = nullptr; |
| 91 Entry* triggered_next = nullptr; |
| 90 }; | 92 }; |
| 91 | 93 |
| 92 WaitSetDispatcher(); | 94 WaitSetDispatcher(); |
| 93 ~WaitSetDispatcher() override; | 95 ~WaitSetDispatcher() override; |
| 94 | 96 |
| 95 // |Dispatcher| protected methods: | 97 // |Dispatcher| protected methods: |
| 96 void CloseImplNoLock() override; | 98 void CloseImplNoLock() override; |
| 97 util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock( | 99 util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock( |
| 98 MessagePipe* message_pipe, | 100 MessagePipe* message_pipe, |
| 99 unsigned port) override; | 101 unsigned port) override; |
| 100 MojoResult WaitSetAddImpl(UserPointer<const MojoWaitSetAddOptions> options, | 102 MojoResult WaitSetAddImpl(UserPointer<const MojoWaitSetAddOptions> options, |
| 101 util::RefPtr<Dispatcher>&& dispatcher, | 103 util::RefPtr<Dispatcher>&& dispatcher, |
| 102 MojoHandleSignals signals, | 104 MojoHandleSignals signals, |
| 103 uint64_t cookie) override; | 105 uint64_t cookie) override; |
| 104 MojoResult WaitSetRemoveImpl(uint64_t cookie) override; | 106 MojoResult WaitSetRemoveImpl(uint64_t cookie) override; |
| 105 MojoResult WaitSetWaitImpl(MojoDeadline deadline, | 107 MojoResult WaitSetWaitImpl(MojoDeadline deadline, |
| 106 UserPointer<uint32_t> num_results, | 108 UserPointer<uint32_t> num_results, |
| 107 UserPointer<MojoWaitSetResult> results, | 109 UserPointer<MojoWaitSetResult> results, |
| 108 UserPointer<uint32_t> max_results) override; | 110 UserPointer<uint32_t> max_results) override; |
| 109 | 111 |
| 110 // |Awakable| implementation: | 112 // |Awakable| implementation: |
| 111 void Awake(uint64_t context, | 113 void Awake(uint64_t context, |
| 112 AwakeReason reason, | 114 AwakeReason reason, |
| 113 const HandleSignalsState& signals_state) override; | 115 const HandleSignalsState& signals_state) override; |
| 114 | 116 |
| 115 void AddPossiblyTriggeredNoLock(Entry* entry, | 117 void AddTriggeredNoLock(Entry* entry) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); |
| 116 Entry::TriggerState new_trigger_state) | 118 void RemoveTriggeredNoLock(Entry* entry) |
| 117 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); | 119 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); |
| 118 void RemovePossiblyTriggeredNoLock(Entry* entry) | |
| 119 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); | |
| 120 | |
| 121 // Set when in the middle of a wait set operation (i.e., |WaitSet...Impl()|) | |
| 122 // with |mutex()| *unlocked*; if attempted (on a different thread), other wait | |
| 123 // set operations should report "busy". Note: Even if |is_busy_| is true, the | |
| 124 // wait set may still be closed. | |
| 125 bool is_busy_ MOJO_GUARDED_BY(mutex()) = false; | |
| 126 | 120 |
| 127 // Map of cookies to entries. | 121 // Map of cookies to entries. |
| 128 using CookieToEntryMap = std::map<uint64_t, std::unique_ptr<Entry>>; | 122 using CookieToEntryMap = std::map<uint64_t, std::unique_ptr<Entry>>; |
| 129 CookieToEntryMap entries_ MOJO_GUARDED_BY(mutex()); | 123 CookieToEntryMap entries_ MOJO_GUARDED_BY(mutex()); |
| 130 | 124 |
| 131 // Intrusive "doubly linked list" (via cookies) of entries that are possibly | 125 // Intrusive "doubly linked list" (via cookies) of entries that are triggered. |
| 132 // satisfied. | 126 Entry* triggered_head_ MOJO_GUARDED_BY(mutex()) = nullptr; |
| 133 Entry* possibly_triggered_head_ MOJO_GUARDED_BY(mutex()) = nullptr; | 127 Entry* triggered_tail_ MOJO_GUARDED_BY(mutex()) = nullptr; |
| 134 Entry* possibly_triggered_tail_ MOJO_GUARDED_BY(mutex()) = nullptr; | |
| 135 // Size of the above list. | 128 // Size of the above list. |
| 136 size_t possibly_triggered_count_ MOJO_GUARDED_BY(mutex()) = 0u; | 129 size_t triggered_count_ MOJO_GUARDED_BY(mutex()) = 0u; |
| 137 | 130 |
| 138 MOJO_DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher); | 131 MOJO_DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher); |
| 139 }; | 132 }; |
| 140 | 133 |
| 141 } // namespace system | 134 } // namespace system |
| 142 } // namespace mojo | 135 } // namespace mojo |
| 143 | 136 |
| 144 #endif // MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ | 137 #endif // MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ |
| OLD | NEW |