• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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