Home | History | Annotate | Download | only in ports
      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 
    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