Class MainModuleEngine

java.lang.Object
io.codetoil.curved_spacetime.MainModuleEngine

public class MainModuleEngine extends Object
The engine: it owns the configuration, the scenes, and the callback loop, and it drives module initialization.

Constructing an engine is what starts the program. The constructor loads the main configuration, registers the initial scene, runs every module's main entrypoint, and then begins the callback loop — so by the time it returns, the whole module graph is up.

Callbacks all run on a single scheduled thread, so implementations need no synchronisation against one another. Module initialization is the opposite: entrypoints run concurrently on an unbounded pool, which the dependency handshake requires — see callDependents(String, Class, Consumer, Logger).

  • Field Details

    • INSTANCE

      protected static MainModuleEngine INSTANCE
      The running engine, set as soon as construction begins so that entrypoints can reach it.
    • mainModuleConfig

      public final MainModuleConfig mainModuleConfig
      The engine's settings, loaded before any module runs.
    • logger

      public final Logger logger
      The logger the engine writes its own diagnostics to.
    • callbackExecutor

      protected final ScheduledExecutorService callbackExecutor
      The single thread every callback runs on.
    • loader

      protected final CurvedSpacetimeLoader loader
      The loader module entrypoints are resolved through.
    • callbackLoopHandler

      protected ScheduledFuture<?> callbackLoopHandler
      Tracks the repeating task that drives every registered callback, cancelled by clean().
    • initialized

      protected boolean initialized
      Is true if the Engine is initialized. Note that this doesn't mean all callbacks are registered, As a callback can be registered at any time and is registered asynchronously.
  • Constructor Details

    • MainModuleEngine

      public MainModuleEngine(CurvedSpacetimeLoader loader)
      Creates the engine and brings the whole module graph up.

      Loads the main configuration, registers the initial scene, runs every main entrypoint, and starts the callback loop at the configured frame rate.

      Parameters:
      loader - the loader that resolves module entrypoints
      Throws:
      RuntimeException - if the main configuration cannot be loaded, or if any module's entrypoint fails
  • Method Details

    • registerScene

      public void registerScene(Scene scene)
      Adds a scene and gives every registered generator a callback for it.
      Parameters:
      scene - the scene to add
    • runEntrypoints

      public void runEntrypoints()
      Prepares the loader and runs every module's main entrypoint.
      Throws:
      RuntimeException - wrapping whatever a module's entrypoint threw
    • callDependents

      public static <E> void callDependents(String name, Class<E> moduleInitializerClass, Consumer<E> onInitialize, Logger logger) throws Throwable
      Invokes every entrypoint registered under the given name, concurrently, and waits for all of them.

      The pool this uses is unbounded, and must remain so. The dependency handshake blocks a consumer in TransferQueue.take while its producer is still to run, so a producer and its consumer have to be runnable at the same time; a bounded pool deadlocks as soon as its threads fill with consumers whose producers are still queued.

      The first entrypoint to fail aborts the whole call rather than leaving a half-initialized module graph running.

      Type Parameters:
      E - the entrypoint type
      Parameters:
      name - the entrypoint name to invoke, such as main
      moduleInitializerClass - the type registered entrypoints must be assignable to
      onInitialize - the action to apply to each entrypoint
      logger - the logger to trace dispatch through
      Throws:
      Throwable - whatever the first failing entrypoint threw
    • getInstance

      public static MainModuleEngine getInstance()
      Returns the running engine.
      Returns:
      the engine, or null before one has been constructed
    • getCurvedSpacetimeLoader

      public CurvedSpacetimeLoader getCurvedSpacetimeLoader()
      Returns the loader this engine resolves entrypoints through.
      Returns:
      the loader
    • registerMainCallback

      public CompletableFuture<Void> registerMainCallback(MainCallback mainCallback)
      Registers scene-independent work and initialises it on the callback thread.
      Parameters:
      mainCallback - the callback to register
      Returns:
      the completable future generated for this task
    • registerSceneCallbackGenerator

      public CompletableFuture<Void> registerSceneCallbackGenerator(Function<Scene, SceneCallback> sceneCallbackGenerator)
      Registers a factory that produces one callback per scene.

      The generator is applied to every scene that exists now, and to each one registered later, so a module never has to track scenes itself.

      Parameters:
      sceneCallbackGenerator - the factory producing a callback for a given scene
      Returns:
      the completable future generated for this task
    • clean

      public void clean()
      Stops the callback loop, releases every callback, and then shuts the callback executor down.
    • throwError

      public void throwError(Throwable t, String message)
      Throws an error and stops the engine.
      Parameters:
      t - the error to throw
      message - the error message
    • getConsoleHandler

      public ConsoleHandler getConsoleHandler()
      Returns the console handler used for the Curved Spacetime Loggers.
      Returns:
      the console handler
    • isInitialized

      public boolean isInitialized()
      Returns whether the Engine is initialized. Note that this doesn't mean all callbacks are registered, As a callback can be registered at any time and is registered asynchronously.
      Returns:
      true if the engine is initialized