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 3 // found in the LICENSE file. 4 5 #ifndef MOJO_CORE_PORTS_PORT_H_ 6 #define MOJO_CORE_PORTS_PORT_H_ 7 8 #include <memory> 9 #include <queue> 10 #include <utility> 11 #include <vector> 12 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/synchronization/lock.h" 16 #include "mojo/core/ports/event.h" 17 #include "mojo/core/ports/message_queue.h" 18 #include "mojo/core/ports/user_data.h" 19 20 namespace mojo { 21 namespace core { 22 namespace ports { 23 24 class PortLocker; 25 26 // A Port is essentially a node in a circular list of addresses. For the sake of 27 // this documentation such a list will henceforth be referred to as a "route." 28 // Routes are the fundamental medium upon which all Node event circulation takes 29 // place and are thus the backbone of all Mojo message passing. 30 // 31 // Each Port is identified by a 128-bit address within a Node (see node.h). A 32 // Port doesn't really *do* anything per se: it's a named collection of state, 33 // and its owning Node manages all event production, transmission, routing, and 34 // processing logic. See Node for more details on how Ports may be used to 35 // transmit arbitrary user messages as well as other Ports. 36 // 37 // Ports may be in any of a handful of states (see State below) which dictate 38 // how they react to system events targeting them. In the simplest and most 39 // common case, Ports are initially created as an entangled pair (i.e. a simple 40 // cycle consisting of two Ports) both in the |kReceiving| State. Consider Ports 41 // we'll label |A| and |B| here, which may be created using 42 // Node::CreatePortPair(): 43 // 44 // +-----+ +-----+ 45 // | |--------->| | 46 // | A | | B | 47 // | |<---------| | 48 // +-----+ +-----+ 49 // 50 // |A| references |B| via |peer_node_name| and |peer_port_name|, while |B| in 51 // turn references |A|. Note that a Node is NEVER aware of who is sending events 52 // to a given Port; it is only aware of where it must route events FROM a given 53 // Port. 54 // 55 // For the sake of documentation, we refer to one receiving port in a route as 56 // the "conjugate" of the other. A receiving port's conjugate is also its peer 57 // upon initial creation, but because of proxying this may not be the case at a 58 // later time. 59 // 60 // ALL access to this data structure must be guarded by |lock_| acquisition, 61 // which is only possible using a PortLocker. PortLocker ensures that 62 // overlapping Port lock acquisitions on a single thread are always acquired in 63 // a globally consistent order. 64 class Port : public base::RefCountedThreadSafe<Port> { 65 public: 66 // The state of a given Port. A Port may only exist in one of these states at 67 // any given time. 68 enum State { 69 // The Port is not yet paired with a peer and is therefore unusable. See 70 // Node::CreateUninitializedPort and Node::InitializePort for motivation. 71 kUninitialized, 72 73 // The Port is publicly visible outside of its Node and may be used to send 74 // and receive user messages. There are always AT MOST two |kReceiving| 75 // Ports along any given route. A user message event sent from a receiving 76 // port is always circulated along the Port's route until it reaches either 77 // a dead-end -- in which case the route is broken -- or it reaches the 78 // other receiving Port in the route -- in which case it lands in that 79 // Port's incoming message queue which can by read by user code. 80 kReceiving, 81 82 // The Port has been taken out of the |kReceiving| state in preparation for 83 // proxying to a new destination. A Port enters this state immediately when 84 // it's attached to a user message and may only leave this state when 85 // transitioning to |kProxying|. See Node for more details. 86 kBuffering, 87 88 // The Port is forwarding all user messages (and most other events) to its 89 // peer without discretion. Ports in the |kProxying| state may never leave 90 // this state and only exist temporarily until their owning Node has 91 // established that no more events will target them. See Node for more 92 // details. 93 kProxying, 94 95 // The Port has been closed and is now permanently unusable. Only 96 // |kReceiving| ports can be closed. 97 kClosed 98 }; 99 100 // The current State of the Port. 101 State state; 102 103 // The Node and Port address to which events should be routed FROM this Port. 104 // Note that this is NOT necessarily the address of the Port currently sending 105 // events TO this Port. 106 NodeName peer_node_name; 107 PortName peer_port_name; 108 109 // The next available sequence number to use for outgoing user message events 110 // originating from this port. 111 uint64_t next_sequence_num_to_send; 112 113 // The sequence number of the last message this Port should ever expect to 114 // receive in its lifetime. May be used to determine that a proxying port is 115 // ready to be destroyed or that a receiving port's conjugate has been closed 116 // and we know the sequence number of the last message it sent. 117 uint64_t last_sequence_num_to_receive; 118 119 // The queue of incoming user messages received by this Port. Only non-empty 120 // for buffering or receiving Ports. When a buffering port enters the proxying 121 // state, it flushes its queue and the proxy then bypasses the queue 122 // indefinitely. 123 // 124 // A receiving port's queue only has elements removed by user code reading 125 // messages from the port. 126 // 127 // Note that this is a priority queue which only exposes messages to consumers 128 // in strict sequential order. 129 MessageQueue message_queue; 130 131 // In some edge cases, a Node may need to remember to route a single special 132 // event upon destruction of this (proxying) Port. That event is stashed here 133 // in the interim. 134 std::unique_ptr<std::pair<NodeName, ScopedEvent>> send_on_proxy_removal; 135 136 // Arbitrary user data attached to the Port. In practice, Mojo uses this to 137 // stash an observer interface which can be notified about various Port state 138 // changes. 139 scoped_refptr<UserData> user_data; 140 141 // Indicates that this (proxying) Port has received acknowledgement that no 142 // new user messages will be routed to it. If |true|, the proxy will be 143 // removed once it has received and forwarded all sequenced messages up to and 144 // including the one numbered |last_sequence_num_to_receive|. 145 bool remove_proxy_on_last_message; 146 147 // Indicates that this Port is aware that its nearest (in terms of forward, 148 // non-zero cyclic routing distance) receiving Port has been closed. 149 bool peer_closed; 150 151 Port(uint64_t next_sequence_num_to_send, 152 uint64_t next_sequence_num_to_receive); 153 AssertLockAcquired()154 void AssertLockAcquired() { 155 #if DCHECK_IS_ON() 156 lock_.AssertAcquired(); 157 #endif 158 } 159 160 private: 161 friend class base::RefCountedThreadSafe<Port>; 162 friend class PortLocker; 163 164 ~Port(); 165 166 base::Lock lock_; 167 168 DISALLOW_COPY_AND_ASSIGN(Port); 169 }; 170 171 } // namespace ports 172 } // namespace core 173 } // namespace mojo 174 175 #endif // MOJO_CORE_PORTS_PORT_H_ 176