Packages

  • package root
    Definition Classes
    root
  • package neko

    ScalaNeko is a framework designed to help with the prototyping of distributed algorithms.

    ScalaNeko Framework

    ScalaNeko is a framework designed to help with the prototyping of distributed algorithms. It is loosely based on the Neko framework [1] which was programmed in Java more than a decade earlier, mainly by Péter Urbán.

    Whereas the original Neko framework was designed for performance evaluation and modeling, the main focus of ScalaNeko is to serve as a support for teaching distributed algorithms. Hence, the current version of ScalaNeko only supports simulated execution. However, we still have the intention to support actual distributed execution in a future version, and hence provide a full replacement of the original Neko.

    1. Architecture

    In order to effectively use ScalaNeko, it is helpful to understand its general architecture, which can be described as follows:

    There are several important entities in ScalaNeko:

    • The system is what handles the execution engine within the virtual machine and the initialization procedure. There is exactly one instance running for every virtual machine. The system also holds a discrete event simulator. See neko.Main and neko.kernel.NekoSystem.
    • The network simulates the behavior of a network, and is responsible for transmitting messages between processes. In the current version, it is running over a discrete-event simulation. See neko.network.Network and neko.kernel.sim.Simulator.
    • The processes are the basic unit of concurrency, and represent a virtual computer connected through a network. Every process has a unique identity represented by a neko.PID. A process does nothing by itself and is merely a shell for protocols. See neko.NekoProcess and neko.ProcessConfig.
    • The protocols are the actual logic of the system and implement the algorithms. A process holds one or many protocols, which are organized as a stack. There are two kinds of protocols: active and reactive ones. While active protocols carry their own flow of execution, that is, act as a thread, concurrently with the system, the reactive protocols only execute code as a reaction to incoming events. See neko.ActiveProtocol, neko.ReactiveProtocol, neko.Protocol, and neko.ProtocolUtils.
    • Protocols and processes exchange information through events. There are two types of events: signals and messages. Signals allow protocols within the same process to notify each other. In contrast, messages allow protocol instances to communicate across different processes. In other words, only messages are transmitted through the network. See neko.Event, neko.Signal, neko.UnicastMessage, neko.MulticastMessage, and neko.Wrapper.

    A simplified view of the architecture of an execution of ScalaNeko is depicted below:

    +-------------------------------------------------------+
    |       process p1                    process pn        |
    |  +-------------------+         +-------------------+  |
    |  | +---------------+ |         | +---------------+ |  |
    |  | | protocol p1:A | |         | | protocol pn:A | |  |
    |  | +-------------+-+ |         | +-------------+-+ |  |
    |  |   |           |   |   ...   |   |           |   |  |
    |  | +-+-----------V-+ |         | +-+-----------V-+ |  |
    |  | | protocol p1:B | |         | | protocol pn:B | |  |
    |  | +-------------+-+ |         | +-------------+-+ |  |
    |  +---|-----------|---+         +---|-----------|---+  |
    |      |           |                 |           |      |
    |  +---+-----------V-----------------+-----------V---+  |
    |  |                      network                    |  |
    |  +-------------------------------------------------+  |
    |                  +------------------+                 |
    |                  |     simulator    |                 |
    |                  +------------------+       system    |
    +-------------------------------------------------------+

    Creating a ScalaNeko application typically requires to implement the following steps:

    1. Implement the protocols. At least, an application will require to implement an active protocol, but also possibly a number of reusable reactive ones.
    2. Each protocol is likely to define its own message types. The most appropriate location for doing so is in a companion object of the protocol. Messages are best defined as a case class so that they are ensured to be immutable and code for pattern matching is automatically generated by the compiler.
    3. Creating a process initializer that instantiates and connects the protocols of the processes.
    4. Creating a main object which provides the basic parameters of the execution, such as the total number of processes to create and their initializer.

    The initialization proceeds roughly as illustrated below:

         creates            creates
    Main ------> NekoSystem ------> Network
                            creates
                      ''    ------> ProcessInitializer
                            creates             creates
                      ''    =====>> NekoProcess =====>> Protocol

    2. Creating protocols

    A protocol can be either active or reactive. An active protocol is one that executes its own thread, concurrently with that of the other protocols or processes. In contrast, a reactive protocol only executes as a reaction to events, and does not do anything otherwise.

    2.1 Active protocols

    An active protocol is typically defined as a subclass of neko.ActiveProtocol.

    An active protocol has its own thread of control. The code of the protocol is implemented in its method neko.ActiveProtocol.run, which must be defined in the subclass. This code is executed concurrently with the rest of the system.

    An active protocol has access to operations for sending and receiving message. New messages are sent with the method neko.ActiveProtocol.SEND. While messages are received through blocking calls to neko.ActiveProtocol.Receive, as illustrated below. Note that, in order to receive messages of a certain type, the protocol must register by calling neko.ActiveProtocol.listenTo for this type.

    class PingPong(c: ProcessConfig) extends ActiveProtocol(c, "ping-pong")
    {
      val next = me.map{i => (i+1) % N}
      var record = Set.empty[Event]
    
      listenTo(classOf[Ping])
      listenTo(classOf[Pong])
      def run(): Unit =
      {
        SEND(Ping(me, next))
    
        Receive {
          case Ping(from, _) => SEND(Pong(me, from))
          case Pong(from, _) => SEND(Ping(me, from))
        }
    
        Receive { m =>
          record += m
        }
      }
    }

    It is also possible to override the method neko.ActiveProtocol.onReceive. By doing so, messages that are matched by onReceive are processed reactively upon arrival, while those that are not matched by onReceive are stored into the receive queue and must be handled by a blocking call to neko.ActiveProtocol.Receive.

    2.2 Reactive protocols

    Most protocols in a process are reactive. A reactive protocol is usually sandwiched between a network and an application (or a lower-level protocol and a higher-level one). The simplest way to implement one is by extending neko.ReactiveProtocol. The information has two flows: downstream and upstream. This is illustrated in the figure below.

             application
      |                      ^
      V                      |
    +----------------------------+
    | onSend        DELIVER(...) |
    |                            | Reactive protocol
    | SEND(...)        onReceive |
    +----------------------------+
      |                      ^
      V                      |
              network

    For the downstream flow (from application to network), the code of the protocol is implemented in the method neko.ReactiveProtocol.onSend, usually implemented as a scala.PartialFunction which reacts as appropriate to each event. The protocol can itself send messages through the neko.ReactiveProtocol.SEND method.

    For the upstream flow (from network to application), the code of the protocol is implemented in the method neko.ReactiveProtocol.onReceive, also implemented as a scala.PartialFunction which reacts appropriately to each incoming events. Events of a certain type are delivered to the protocol only if it registers to the event type by calling the neko.ReactiveProtocol.listenTo method on that event type. The protocol can deliver a message to the application through the method neko.ReactiveProtocol.DELIVER.

    Note that the two flows are not mutually exclusive. It is perfectly valid, and even frequent, for a protocol to call neko.ReactiveProtocol.DELIVER in neko.ReactiveProtocol.onSend, or to call neko.ReactiveProtocol.SEND in neko.ReactiveProtocol.onReceive .

    3. Defining new events (messages and signals)

    Let's start with a little bit of terminology. An event denotes anything that happens in the system and is represented by the abstract class neko.Event. Events can be of two types:

    • A signal is an event that occurs within one process, and can go from one protocol to another, but never cross process boundaries. It is represented by the subclasses of neko.Signal.
    • A message is an event that crosses process boundaries, but is typically (but not necessarily) interpreted by the same protocol in the target process. It is represented by the subclasses of neko.Message.

    A message can be "top-level" or a "wrapper". A top-level message is one that is created by the sending protocol. It has its own identity, as well as a source and destinations. In contrast, a wrapper is simply a shell that extends the information of an existing message. It retains the same identity, source, and destinations, but provides a shell to the message and can add its own information. This results into messages of three types:

    • A neko.MulticastMessage is a top-level message with multiple destinations. See the example below on how to define a new message:
    case class Snapshot(
        from: PID,
        to: Set[PID])
      extends MulticastMessage

    NB: The arguments *must* be named from and to.

    case class Token (
        from: PID,
        to: PID)
      extends UnicastMessage

    NB: The arguments *must* be named from and to.

    • A neko.Wrapper is a shell that wraps an existing message. A wrapper can also extend another wrapper; not only top-level messages. A wrapper preserves the identity, the source and the destinations of the message it wraps.
    case class SequencedMessage(msg: Message, sn: Int) extends Wrapper(msg)

    4. Initialization of a process

    While processes are created automatically, their protocols are not, and must be initialized and connected. This is done through a process initializer, by providing an instance of neko.ProcessInitializer, whose sole role is to create the protocols of a process and combine them.

    ProcessInitializer { p =>
        val app  = new PingPong(p)
        val fifo = new FIFOChannel(p)
        app --> fifo
      }

    In the above example, each process is initialized by executing the above code. The code creates two protocols while registering them into the object p given as argument (which represents the process being initialized). Then, the two protocols are connected such that all SEND operations of protocol app are handed to protocol fifo. The send operations of protocol fifo use the default target which is the network interface of the process.

    It is also possible to initialize processes differently, by discriminating based on the identifier of the process to initialize. That identifier is obtained from the argument with p.pid.

    5. Setting up a new system

    A new instance of a ScalaNeko system is created and configured by creating an object that extends neko.Main. The resulting object becomes a main object and is thus executable (neko.Main is a subclass of scala.App).

    Class neko.Main requires to set parameters, such as the network topology and the process initializer, as illustrated below:

    object PingPongApp extends Main(topology.Clique(3))( ProcessInitializer { p=> ... } )

    Future planned versions of ScalaNeko will make it possible to define many more parameters, such as the network topologyDescriptor, etc...

    References

    1. Péter Urbán, Xavier Défago, André Schiper: Neko: A Single Environment to Simulate and Prototype Distributed Algorithms. J. Inf. Sci. Eng. 18(6): 981-997 (2002).

    Contributors

    Lead architect: Xavier Défago

    Other contributors:

    • Naoyuki Onuki (trace system; integration with NekoViewer)
    Definition Classes
    root
  • package protocol
    Definition Classes
    neko
  • AnonymousRounds
  • ArbitraryTopology
  • FIFOChannel
  • FastAnonymousRounds
  • LamportClock
  • RoundBased
  • RoundBasedWithFailures
  • SafraTerminationDetection
  • SynchronousRounds
  • VectorClock

class ArbitraryTopology extends ReactiveProtocol with Topology with LazyLogging

Support for simulating arbitrary network topologies.

The topologyDescriptor is given as a graph (see http://www.scala-graph.org/api/core/api/#scalax.collection.Graph). A message sent by a process p is delivered to another process q only if q is a neighbor of p in the graph. The protocol can also be queried through the neko.util.Topology trait, to obtain the set of neighbors

By default, the topologyDescriptor is a clique of all the processes, but other ready-made graphs can also be found in neko.util.Topology.

Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. ArbitraryTopology
  2. LazyLogging
  3. Topology
  4. ReactiveProtocol
  5. Tracing
  6. Receiving
  7. Sending
  8. Sender
  9. ListenerUtils
  10. Listener
  11. Receiver
  12. ProtocolImpl
  13. ProtocolUtils
  14. Protocol
  15. NamedEntity
  16. AnyRef
  17. Any
Implicitly
  1. by any2stringadd
  2. by StringFormat
  3. by Ensuring
  4. by ArrowAssoc
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Instance Constructors

  1. new ArbitraryTopology(config: ProcessConfig, topology: Graph[Int, UnDiEdge])

    config

    the process on which the protocol runs.

    topology

    a graph describing the whole network topologyDescriptor. A warning is issued when the graph is not connected.

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. def +(other: String): String
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to any2stringadd[ArbitraryTopology] performed by method any2stringadd in scala.Predef.
    Definition Classes
    any2stringadd
  4. def -->(sender: Sender): Unit

    Connects a new sender to this protocol.

    Connects a new sender to this protocol.

    sender

    the new sender to connect.

    Definition Classes
    ProtocolUtils
  5. def ->[B](y: B): (ArbitraryTopology, B)
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to ArrowAssoc[ArbitraryTopology] performed by method ArrowAssoc in scala.Predef.
    Definition Classes
    ArrowAssoc
    Annotations
    @inline()
  6. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  7. lazy val ALL: Set[PID]

    set of all processes in the system.

    set of all processes in the system.

    Attributes
    protected[this]
    Definition Classes
    ProtocolUtils
  8. def BROADCAST(m: BroadcastMessage): Unit

    Broadcasts a message using the sender set in the initializer where the protocol is created.

    Broadcasts a message using the sender set in the initializer where the protocol is created. If no sender was explicitly set, the message will be set directly through the network. This is a wrapper for SEND

    m

    the message to broadcast

    Definition Classes
    Receiving
  9. def DELIVER(m: Event): Unit

    provides the message or signal to the application.

    provides the message or signal to the application. The message or signal passed as argument will be delivered to any protocol that has registered (e.g., using the method ListenerUtils!.listenTo) for this type of message/signal to the dispatcher providing in receiver.

    m

    the message or signal to deliver

    Definition Classes
    ReactiveProtocolSending
  10. lazy val N: Int

    total number of processes running in the system.

    total number of processes running in the system.

    Attributes
    protected[this]
    Definition Classes
    ProtocolUtils
  11. def SEND(m: Event): Unit

    Sends a message using the sender set in the initializer where the protocol is created.

    Sends a message using the sender set in the initializer where the protocol is created. If no sender was explicitly set, the message will be set directly through the network. The destination for the message is defined when the message is created.

    m

    the message/signal to send

    Definition Classes
    ReactiveProtocolReceiving
  12. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  13. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... ) @native() @HotSpotIntrinsicCandidate()
  14. def context: Some[PID]
    Definition Classes
    ProtocolNamedEntity
  15. def deliver(m: Event): Unit
    Definition Classes
    ReactiveProtocolReceivingReceiver
  16. def dispatcher: Dispatcher

    dispatcher to be used when delivering messages.

    dispatcher to be used when delivering messages. Typically, this is the default dispatcher of the process.

    returns

    dispatcher for message delivery

    Definition Classes
    ProtocolImpl
  17. def ensuring(cond: (ArbitraryTopology) ⇒ Boolean, msg: ⇒ Any): ArbitraryTopology
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to Ensuring[ArbitraryTopology] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  18. def ensuring(cond: (ArbitraryTopology) ⇒ Boolean): ArbitraryTopology
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to Ensuring[ArbitraryTopology] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  19. def ensuring(cond: Boolean, msg: ⇒ Any): ArbitraryTopology
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to Ensuring[ArbitraryTopology] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  20. def ensuring(cond: Boolean): ArbitraryTopology
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to Ensuring[ArbitraryTopology] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  21. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  22. def equals(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  23. def eventTracer: EventTracer
    Definition Classes
    ProtocolImpl
  24. def formatted(fmtstr: String): String
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to StringFormat[ArbitraryTopology] performed by method StringFormat in scala.Predef.
    Definition Classes
    StringFormat
    Annotations
    @inline()
  25. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  26. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  27. val id: ProtoID

    identifier of the protocol.

    identifier of the protocol.

    returns

    identifier of the protocol

    Definition Classes
    ProtocolImplProtocol
  28. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  29. def listenTo(clazz: Class[_ <: Event]): Unit

    called by the protocol to declare that it will listen to messages/event of the given type.

    called by the protocol to declare that it will listen to messages/event of the given type.

    class MyProtocol(...) extends ... with ListenerUtils
    {
      listenTo(classOf[MyMessage])
      listenTo(MyAlarm.getClass)
      def onReceive = {
        case MyMessage(...) => ...
        case MyAlarm        => ...
      }
    }
    object MyProtocol
    {
      case class MyMessage(...) extends UnicastMessage(...)
      case object MyAlarm extends Signal
    clazz

    type of the message/event to listen to

    Attributes
    protected[this]
    Definition Classes
    ListenerUtilsListener
  30. lazy val logger: Logger
    Attributes
    protected
    Definition Classes
    LazyLogging
    Annotations
    @transient()
  31. lazy val me: PID

    identifier of the process in which the protocol is running.

    identifier of the process in which the protocol is running.

    Attributes
    protected[this]
    Definition Classes
    ProtocolUtils
  32. val myNode: scalax.collection.Graph.NodeT
    Attributes
    protected[this]
  33. def name: String

    returns the name of the protocol

    returns the name of the protocol

    returns

    name of the protocol

    Definition Classes
    ProtocolNamedEntity
  34. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  35. val neighborhood: Set[Int]
    Definition Classes
    ArbitraryTopologyTopology
  36. lazy val neighbors: Set[PID]

    set of processes that are direct neighbors to the process in which this instance of the protocol runs.

    set of processes that are direct neighbors to the process in which this instance of the protocol runs.

    Attributes
    protected[this]
    Definition Classes
    ProtocolUtils
  37. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  38. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @HotSpotIntrinsicCandidate()
  39. def onError(e: Throwable): Unit

    override this method to report on errors whens the protocol is forcibly terminated due to an an error or exception.

    override this method to report on errors whens the protocol is forcibly terminated due to an an error or exception. The method should never use any of the communication methods such as send, receive, or deliver.

    Definition Classes
    Protocol
  40. final def onFinish(): Unit

    this method does nothing for reactive protocols; take downs should instead override the method onShutdown.

    this method does nothing for reactive protocols; take downs should instead override the method onShutdown.

    Definition Classes
    ReactiveProtocolProtocol
  41. def onReceive: PartialFunction[Event, Unit]

    Implements the behavior of the protocol when receiving a message (or signal).

    Implements the behavior of the protocol when receiving a message (or signal).

    This must be defined in any concrete subclass. It is defined as a partial function taking a message as input and returning nothing.

    Typically, the partial function will implement different behavior depending on the type of message being sent. For instance,

    def onReceive = {
      case Token(from, _, _) if parent.isEmpty =>
        parent   = Some(from)
        children = (neighbors-from).toList
        DELIVER (Visit)
        visitNextChild()
      case Token(_, _, _) => visitNextChild()
    }
    Definition Classes
    ArbitraryTopologyReceiving
  42. def onSend: PartialFunction[Event, Unit]

    Implements the behavior of the protocol when sending a message.

    Implements the behavior of the protocol when sending a message.

    This must be defined in any concrete subclass. It is defined as a partial function taking a message as input and returning nothing.

    Typically, the partial function will implement different behavior depending on the type of message being sent. For instance,

    def onSend = {
      case MutexClient.Request =>
        want = true ; myTS = lc.time
        SEND(Request(me, ALL-me, myTS))
      case MutexClient.Release =>
        SEND(Ack(me, pendingAcks))
        ackCount = 0 ; want = false ; pendingAcks = Set.empty
    }
    Definition Classes
    ArbitraryTopologySending
  43. def onShutdown(): Unit

    override this method to perform take downs after all processes have finished and before the process shuts down.

    override this method to perform take downs after all processes have finished and before the process shuts down.

    Definition Classes
    Protocol
  44. def out: PrintWriter
    Definition Classes
    ProtocolImpl
  45. def preStart(): Unit

    override this method to perform initializations just before the process begins to run.

    override this method to perform initializations just before the process begins to run.

    Definition Classes
    Protocol
  46. def process: PID

    identifier of the process to which the protocol is attached.

    identifier of the process to which the protocol is attached.

    returns

    identifier of the process

    Definition Classes
    ProtocolImplProtocol
  47. def receiver: Receiver

    receiver to which this protocol delivers messages.

    receiver to which this protocol delivers messages. Typically, this is the message dispatcher of the process.

    returns

    receiver to which messages are delivered

    Definition Classes
    ProtocolUtils
  48. def receiver_=(receiver: Receiver): Unit

    sets a new receiver to which this protocol will deliver messages.

    sets a new receiver to which this protocol will deliver messages. Normally, there is no need for the application programmer to use this, as the receiver is automatically set to a meaningful default value.

    receiver

    new receiver to which messages will be delivered

    Definition Classes
    ProtocolUtils
  49. def send(m: Event): Unit

    Used to request the protocol to send a given message.

    Used to request the protocol to send a given message.

    The function translates to a call to onSend in order to handle the message.

    m

    the message to send

    Definition Classes
    ReactiveProtocolSendingSender
  50. def sender: Sender

    target sender that will handle Sending#send operations for this protocol.

    target sender that will handle Sending#send operations for this protocol.

    returns

    target sender

    Definition Classes
    ProtocolUtils
  51. def senderOpt: Option[Sender]
    Definition Classes
    ProtocolUtils
  52. def setTrace[A](obj: A, nameOfVariable: String*)(implicit arg0: scala.reflect.api.JavaUniverse.TypeTag[A], arg1: ClassTag[A]): Unit
    Definition Classes
    ReactiveProtocol
  53. def simpleName: String
    Definition Classes
    ProtocolNamedEntity
  54. def start(): Unit

    override this method to perform initialization just as the process starts.

    override this method to perform initialization just as the process starts.

    Definition Classes
    Protocol
  55. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  56. def system: NekoSystem

    system in which the protocol is running.

    system in which the protocol is running. This gives access to some general information about the system, such as the total number of processes.

    returns

    the system in which the protocol runs.

    Definition Classes
    ProtocolImplProtocol
  57. def toDotString: String
    Definition Classes
    Topology
  58. def toString(): String
    Definition Classes
    ProtocolImpl → AnyRef → Any
  59. val topology: Graph[Int, UnDiEdge]
    Definition Classes
    ArbitraryTopologyTopology
  60. val tracer: EventTracer
    Attributes
    protected
    Definition Classes
    Tracing
  61. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  62. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... ) @native()
  63. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  64. def [B](y: B): (ArbitraryTopology, B)
    Implicit
    This member is added by an implicit conversion from ArbitraryTopology to ArrowAssoc[ArbitraryTopology] performed by method ArrowAssoc in scala.Predef.
    Definition Classes
    ArrowAssoc

Deprecated Value Members

  1. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] ) @Deprecated @deprecated
    Deprecated

    (Since version ) see corresponding Javadoc for more information.

Inherited from LazyLogging

Inherited from Topology

Inherited from ReactiveProtocol

Inherited from Tracing

Inherited from Receiving

Inherited from Sending

Inherited from Sender

Inherited from ListenerUtils

Inherited from Listener

Inherited from Receiver

Inherited from ProtocolImpl

Inherited from ProtocolUtils

Inherited from Protocol

Inherited from NamedEntity

Inherited from AnyRef

Inherited from Any

Inherited by implicit conversion any2stringadd from ArbitraryTopology to any2stringadd[ArbitraryTopology]

Inherited by implicit conversion StringFormat from ArbitraryTopology to StringFormat[ArbitraryTopology]

Inherited by implicit conversion Ensuring from ArbitraryTopology to Ensuring[ArbitraryTopology]

Inherited by implicit conversion ArrowAssoc from ArbitraryTopology to ArrowAssoc[ArbitraryTopology]

Ungrouped