Class EConfigure.Dispatcher

  • All Implemented Interfaces:
    Comparable<EConfigure.Dispatcher>
    Enclosing class:
    EConfigure

    public static final class EConfigure.Dispatcher
    extends EConfigure.ThreadConfig
    implements Comparable<EConfigure.Dispatcher>
    eBus uses a Dispatcher to forward messages to client. While Dispatchers cannot be accessed by an application, an application can configure Dispatchers. In order to configure a Dispatcher, you need to know how Dispatchers work.

    eBus wraps client callbacks in Runnable task instances. Each eBus client has an Queue<Runnable> containing the callback tasks for the client. So when a callback task is created, it is added to the client’s task queue. When the client task queue is empty and no callback task is being run, then the client is idle. When a new callback task is added to an idle client, then the client becomes runnable.

    When a client transitions from idle to runnable, then the client is added to its Dispatcher run queue. Each client is associated with one Dispatcher run queue. A Dispatcher has a run queue of runnable clients and one or more threads watch the run queue for runnable clients to arrive. One thread removes the client from the run queue and then starts executing the client’s queue tasks. The client is now in the running state.

    The queued client tasks are executed until either the task queue is empty or the client exhausts its run quantum. If a run quantum is used, then it is reset to the configured amount when the client transitions from idle to runnable or when the quantum is exhausted. When exhausted, the client transitions from running to runnable and put back on the LIFO run queue.

    Note: eBus does not use a preempting run quantum. If a client callback goes into an infinite loop, then that callback will take over the Dispatcher thread. The Dispatcher thread only checks if the quantum is exceeded when the callback returns. Since the callback in this example never returns, the Dispatcher thread does not detect that the run quantum is exceeded.

    Dispatchers are created either in an eBus configuration file which is loaded at JVM start using the Java command line option -Dnet.sf.eBus.config.jsonFile=<config file path> or dynamically using net.sf.eBus.client.EFeed.createDispatcher(EConfigure.Dispatcher). The command line option is preferred since a Dispatcher must be instantiated prior to assigning an eBus client to the dispatcher. If using dynamic Dispatcher creation, care must be given to do so before eBus client assignment.

    Creating eBus Dispatchers

    An application may create dispatch threads with a given unique name and JSON properties listed below.

    Dispatcher JSON Properties
    Property Required? Type Default Description
    name Yes String NA Non-empty text representing unique dispatcher name.
    taskQueueCapacity No int > zero EConfigure.DEFAULT_TASK_QUEUE_CAPACITY eBus client task queue capacity. Value should be an exact 2 power. If not, queue size is set to next 2 power > given capacity.
    runQueueType No ThreadType EConfigure.DEFAULT_THREAD_TYPE Dispatcher thread is implemented as this type.
    runQueueCapacity No int > zero EConfigure.DEFAULT_TASK_QUEUE_CAPACITY Run queue capacity. Value should be an exact 2 power. If not, queue size is set to next 2 power > given capacity.
    priority No intThread.MIN_PRIORITY and ≤ Thread.MAX_PRIORITY. EConfigure.DEFAULT_PRIORITY Thread scheduling priority. Must be ≥ Thread.MIN_PRIORITY and ≤ Thread.MAX_PRIORITY.
    quantum No int EConfigure.DEFAULT_QUANTUM Task run-time quantum. Does not pre-empt tasks which exceed this time limit.
    numberThreads No int > zero EConfigure.DEFAULT_NUMBER_THREADS Dispatcher contains this many threads.
    isDefault No boolean false If true marks this as the default dispatcher. Only one dispatcher may be marked as the default.
    classes Yes if isDefault is false Array of Class names. May not be empty. Class names must be accessible to this JVM instance. NA Dispatcher handles instances of these classes.
    threadAffinities No Array of ThreadAffinityConfigure Empty list Optional OpenHFT thread affinity configurations.

    Example dispatcher configuration.

    name : d1
    taskQueueCapacity : 256
    runQueueType : "spin+park"
    runQueueCapacity : 2048
    spinLimit : 2500000
    parkTime : 500ns
    isDefault : true
    priority : 5
    quantum : 10000ns
    numberThreads : 4

    Programmatic Dispatcher Configuration

    Dispatchers may be created at run time using EConfigure.DispatcherBuilder. The following example creates a spinning, single thread Dispatcher for the singleton MarketDataHandler instance.

    Note: This example only works if the dispatcher is created before MarketDataHandler instantiated. If not, the MarketDataHandler instance will be assigned to the default Dispatcher.

    import net.sf.eBus.client.EFeed;
    import net.sf.eBus.config.EConfigure;
    import net.sf.eBus.config.EConfigure.Dispatcher;
    import net.sf.eBus.config.EConfigure.DispatcherBuilder;
    import net.sf.eBus.config.EConfigure.DispatcherType;
    import net.sf.eBus.config.EConfigure.ThreadAffinityConfigure;
    import net.sf.eBus.config.ThreadType;
    
    public static void main(final String[] args) {
        final Class[] eclients = new Class[] { MarketDataHandler.class };
        final ThreadAffinityConfigure threadAffinity =
            (ThreadAffinityConfigure.builder()).affinityType(ThreadsAffinityConfigure.AffinityType.CPU_ID)
                                               .cpuId(7)
                                               .bind(true)
                                               .wholeCore(true)
                                               .build();
        final ThreadAffinityConfigure[] threadAffinities =
            new ThreadAffinityConfigure[] { threadAffinity };
        final DispatcherBuilder builder = EConfigure.dispatcherBuilder();
        final Dispatcher dispatcher = builder.name("MyDispatcher")
                                             .taskQueueCapacity(256)
                                             .dispatcherType(DispatcherType.EBUS)
                                             .threadType(ThreadType.SPINNING)
                                             .runQueueCapacity(2048)
                                             .numberThreads(1)
                                             .isDefault(false)
                                             .classes(eclients)
                                             .threadAffinity(threadAffinities)
                                             .build();
    
        EFeed.createDispatcher(dispatcher);
    }

    See ThreadAffinityConfigure.Builder for explanation on how to build a ThreadAffinityConfigure instances.

    Special Dispatchers

    There are two special, pre-defined eBus Dispatcher names: "swing" and "javafx" (case insensitive). These Dispatchers use the Swing/JavaFX GUI thread to deliver eBus messages to a client. This means that the client callback is free to update the GUI because the callback code is running on the GUI thread.

    Only two properties are supported by special Dispatchers: EConfigure.DEFAULT_KEY and EConfigure.CLASSES_KEY. All other properties are ignored by special Dispatchers. The reason is that the underlying GUI threads are implemented and configured by the GUI package and cannot be altered by eBus.

    It may be useful to define the GUI thread Dispatcher as the default Dispatcher and then create a separate eBus Dispatcher for non-GUI classes. This way, an application class updating the display will be assigned to the GUI thread without needing to add that class to the GUI Dispatcher classes property.

    • Method Detail

      • dispatchType

        public EConfigure.DispatcherType dispatchType()
        Returns the dispatch method type.
        Returns:
        dispatch method type.
      • runQueueType

        public ThreadType runQueueType()
        Returns the run queue type which defines how the thread acquires the next available eBus client.
        Returns:
        run queue operation type.
      • taskQueueCapacity

        public int taskQueueCapacity()
        Returns eBus client task queue capacity.
        Returns:
        eBus client task queue capacity.
      • runQueueCapacity

        public int runQueueCapacity()
        Returns run queue maximum capacity. Used only for non-blocking run queue types and ignored for blocking run queue.
        Returns:
        non-blocking run queue maximum capacity.
      • isDefault

        public boolean isDefault()
        Returns true if this user-defined dispatcher is the default dispatcher.
        Returns:
        true if the default dispatcher.
      • classes

        public Class<?>[] classes()
        Returns the classes assigned to this dispatcher. Returned array may be empty but will not be null.
        Returns:
        dispatcher class array.
      • quantum

        public Duration quantum()
        Returns the client run-time quantum assigned by this dispatcher.
        Returns:
        client run-time quantum.
      • numberThreads

        public int numberThreads()
        Returns the number of threads in this dispatcher.
        Returns:
        dispatcher thread count.