Interface ISideEffectFactory


public interface ISideEffectFactory

A factory to create ISideEffect objects, which are applied to the given Consumer in createFactory(Consumer).

Callers who provide the Consumer<ISideEffect> for the creation of an ISideEffectFactory, are supposed to manage the lifecycle of the aggregated ISideEffect instances, which are created by this factory.
Since:
1.6
See Also:
Restriction:
This interface is not intended to be implemented by clients.
  • Method Details

    • createFactory

      static ISideEffectFactory createFactory(Consumer<ISideEffect> sideEffectConsumer)
      Creates a new ISideEffectFactory which will notify the given Consumer of every ISideEffect that is constructed by the factory.

      For example, a Consumer could be passed to this method which automatically inserts every ISideEffect into the same CompositeSideEffect, allowing their lifecycle to be managed automatically by the object which provides the factory.

      Callers who invoke this createFactory(Consumer) method are supposed to manage the lifecycle of the aggregated ISideEffect instances, which are created by this factory. They do so by passing in a consumer which collects the side-effects constructed by the factory, allowing ISideEffect.dispose() to be invoked on them at a later time.

      Parameters:
      sideEffectConsumer - a consumer which will be notified about every ISideEffect constructed by this factory. The consumer must guarantee that ISideEffect.dispose() will be called on every ISideEffect it receives at some point in the future.
      Returns:
      a newly constructed ISideEffectFactory
      See Also:
    • createPaused

      ISideEffect createPaused(Runnable runnable)
      Creates a new ISideEffect on the default Realm but does not run it immediately. The lifecycle of the returned ISideEffect will be managed by the factory.

      Callers are not required to dispose the resulting ISideEffect, but may do so if they wish to dispose it early.

      This is similar to ISideEffect.createPaused(Runnable) except that the resulting ISideEffect will have its lifecycle managed by the factory.

      Parameters:
      runnable - the runnable to execute. Must be idempotent.
      Returns:
      a newly-created ISideEffect which has not yet been activated. Callers may call ISideEffect.dispose() on the result if they wish to dispose it early, but they are not required to do so since the lifecycle of the returned ISideEffect is managed automatically.
    • createPaused

      ISideEffect createPaused(Realm realm, Runnable runnable)
      Creates a new ISideEffect on the given Realm but does not activate it immediately. Callers are not required to dispose the resulting ISideEffect, but may do so if they wish to dispose it early.

      This is similar to ISideEffect.createPaused(Realm, Runnable) except that the resulting ISideEffect will have its lifecycle managed by the factory.

      Parameters:
      realm - the realm to execute
      runnable - the runnable to execute. Must be idempotent.
      Returns:
      a newly-created ISideEffect which has not yet been activated. Callers may call ISideEffect.dispose() on the result if they wish to dispose it early, but they are not required to do so since the lifecycle of the returned ISideEffect is managed automatically.
    • create

      ISideEffect create(Runnable runnable)
      Runs the given runnable once synchronously. The runnable will then run again after any tracked getter invoked by the runnable changes. It will continue doing so until the returned ISideEffect is disposed. The returned ISideEffect is associated with the default realm.

      Callers are not required to dispose the resulting ISideEffect, but may do so if they wish to dispose it early.

      This is similar to ISideEffect.create(Runnable) except that the resulting ISideEffect will have its lifecycle managed by the factory.

      Parameters:
      runnable - an idempotent runnable which will be executed once synchronously then additional times after any tracked getter it uses changes state
      Returns:
      an ISideEffect interface that may be used to stop the side-effect from running. The Runnable will not be executed anymore after the dispose method is invoked. Callers may call ISideEffect.dispose() on the result if they wish to dispose it early, but they are not required to do so since the lifecycle of the returned ISideEffect is managed automatically.
    • create

      <T> ISideEffect create(Supplier<T> supplier, Consumer<T> consumer)
      Runs the supplier and passes its result to the consumer. The same thing will happen again after any tracked getter invoked by the supplier changes. It will continue to do so until the given ISideEffect is disposed. The returned ISideEffect is associated with the default realm.

      Callers are not required to dispose the resulting ISideEffect, but may do so if they wish to dispose it early.

      The ISideEffect will initially be in the resumed state.

      The first invocation of this method will be synchronous. This version is slightly more efficient than createResumed(Supplier, Consumer) and should be preferred if synchronous execution is acceptable.

      This is similar to ISideEffect.create(Supplier, Consumer) except that the resulting ISideEffect will have its lifecycle managed by the factory.

      Parameters:
      supplier - a supplier which will compute a value and be monitored for changes in tracked getters. It should be side-effect-free.
      consumer - a consumer which will receive the value. It should be idempotent. It will not be monitored for tracked getters.
      Returns:
      an ISideEffect interface that may be used to stop the side-effect from running. The Runnable will not be executed anymore after the dispose method is invoked. Callers may call ISideEffect.dispose() on the result if they wish to dispose it early, but they are not required to do so since the lifecycle of the returned ISideEffect is managed automatically.
    • createResumed

      <T> ISideEffect createResumed(Supplier<T> supplier, Consumer<T> consumer)
      Runs the supplier and passes its result to the consumer. The same thing will happen again after any tracked getter invoked by the supplier changes. It will continue to do so until the given ISideEffect is disposed. The returned ISideEffect is associated with the default realm.

      Callers are not required to dispose the resulting ISideEffect, but may do so if they wish to dispose it early.

      The ISideEffect will initially be in the resumed state.

      The first invocation of this method will be asynchronous. This is useful, for example, when constructing an ISideEffect in a constructor since it ensures that the constructor will run to completion before the first invocation of the ISideEffect. However, this extra safety comes with a small performance cost over create(Supplier, Consumer).

      This is similar to ISideEffect.createResumed(Supplier, Consumer) except that the resulting ISideEffect will have its lifecycle managed by the factory.

      Parameters:
      supplier - a supplier which will compute a value and be monitored for changes in tracked getters. It should be side-effect-free.
      consumer - a consumer which will receive the value. It should be idempotent. It will not be monitored for tracked getters.
      Returns:
      an ISideEffect interface that may be used to stop the side-effect from running. The Runnable will not be executed anymore after the dispose method is invoked. Callers may call ISideEffect.dispose() on the result if they wish to dispose it early, but they are not required to do so since the lifecycle of the returned ISideEffect is managed automatically.
    • consumeOnceAsync

      <T> ISideEffect consumeOnceAsync(Supplier<T> supplier, Consumer<T> consumer)
      Runs the given supplier until it returns a non-null result. The first time it returns a non-null result, that result will be passed to the consumer and the ISideEffect will dispose itself. As long as the supplier returns null, any tracked getters it invokes will be monitored for changes. If they change, the supplier will be run again at some point in the future.

      The resulting ISideEffect will be dirty and resumed, so the first invocation of the supplier will be asynchronous. If the caller needs it to be invoked synchronously, they can call ISideEffect.runIfDirty()

      Unlike create(Supplier, Consumer), the consumer does not need to be idempotent.

      This method is used for gathering asynchronous data before opening an editor, saving to disk, opening a dialog box, or doing some other operation which should only be performed once.

      Consider the following example, which displays the content of a text file in a message box without doing any file I/O on the UI thread.

       IObservableValue<String> loadFileAsString(String filename) {
         // Uses another thread to load the given filename. The resulting observable returns
         // null if the file is not yet loaded or contains the file contents if the file is
         // fully loaded
         // ...
       }
      
       void showFileContents(Shell parentShell, String filename) {
         IObservableValue<String> webPageContent = loadFileAsString(filename);
         ISideEffect.runOnce(webPageContent::getValue, (content) -> {
              MessageDialog.openInformation(parentShell, "Your file contains", content);
         })
       }
       
      This is similar to ISideEffect.consumeOnceAsync(Supplier, Consumer) except that the resulting ISideEffect will have its lifecycle managed by the factory.
      Parameters:
      supplier - supplier which returns null if the side-effect should continue to wait or returns a non-null value to be passed to the consumer if it is time to invoke the consumer
      consumer - a (possibly non-idempotent) consumer which will receive the first non-null result returned by the supplier.
      Returns:
      a side-effect which can be used to control this operation. If it is disposed before the consumer is invoked, the consumer will never be invoked. It will not invoke the supplier if it is paused.