Package ghidra.app.services

# Interface ProgressService

public interface ProgressService
A service for publishing and subscribing to tasks and progress notifications.

This is an attempt to de-couple the concepts of task monitoring and task execution. The `PluginTool` has a system for submitting background tasks. It queues the task. When it reaches the front of the queue, it creates a `TaskMonitor`, starts a thread, and executes the task. Unfortunately, this tightly couples the progress reporting system with the execution model, which is not ideal. Moreover, the task queuing system is the only simple way to obtain a `TaskMonitor` with any semblance of central management or consistent presentation. Providers can (and often do) create their own `TaskMonitor`s, usually placed at the bottom of the provider when it is, e.g., updating a table.

This service attempts to provide a centralized system for creating and presenting `TaskMonitor`s separate from the execution model. No particular execution model is required. Nor is the task implicitly associated to a specific thread. A client may use a single thread for all tasks, a single thread for each task, many threads for a task, etc. In fact, a client could even use an `ExecutorService`, without any care to how tasks are executed. Instead, a task need simply request a monitor, pass its handle as needed, and close it when finished. The information generated by such monitors is then forwarded to the subscriber which can determine how to present them.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `addProgressListener(ProgressListener listener)`
  Subscribe to task and progress events
  `default <T> CompletableFuture<T>`
  `execute(boolean canCancel, boolean hasProgress, boolean isModal, Function<TaskMonitor,CompletableFuture<T>> futureSupplier)`
  Similar to `execute(Task)`, but for asynchronous methods
  `default CompletableFuture<Void>`
  `execute(Task task)`
  A drop-in replacement for `PluginTool.execute(Task)` that publishes progress via the service rather than displaying a dialog.
  `Collection<MonitorReceiver>`
  `getAllMonitors()`
  Collect all the tasks currently in progress
  `CloseableTaskMonitor`
  `publishTask()`
  Publish a task and create a monitor for it
  `void`
  `removeProgressListener(ProgressListener listener)`
  Un-subscribe from task and progress events

- ## Method Details

  - ### publishTask

    CloseableTaskMonitor publishTask()
    Publish a task and create a monitor for it

    This and the methods on `TaskMonitor` are the mechanism for clients to publish task and progress information. The monitor returned also extends `AutoCloseable`, allowing it to be used fairly safely when the execution model involves a single thread.

         try (CloseableTaskMonitor monitor = progressService.publishTask()) {
                // Do the computation and update the monitor accordingly.
         }

    If the above idiom is not used, e.g., because the monitor is passed among several `CompletableFuture`s, the client must take care to close it. While the service may make some effort to clean up dropped handles, this is just a safeguard to prevent stale monitors from being presented indefinitely. The service may complain loudly when it detects dropped monitor handles.

    Returns:
      the monitor

  - ### getAllMonitors

    Collection<MonitorReceiver> getAllMonitors()
    Collect all the tasks currently in progress

    The subscriber ought to call this immediately after adding its listener, in order to catch up on tasks already in progress.

    Returns:
      a collection of in-progress monitor proxies

  - ### addProgressListener

    void addProgressListener(ProgressListener listener)
    Subscribe to task and progress events
    Parameters:
      `listener` - the listener

  - ### removeProgressListener

    void removeProgressListener(ProgressListener listener)
    Un-subscribe from task and progress events
    Parameters:
      `listener` - the listener

  - ### execute

    default CompletableFuture<Void> execute(Task task)
    A drop-in replacement for `PluginTool.execute(Task)` that publishes progress via the service rather than displaying a dialog.

    In addition to changing how progress is displayed, this also returns a future so that task completion can be detected by the caller.

    Parameters:
      `task` - task to run in a new thread
    Returns:
      a future which completes when the task is finished

  - ### execute

    default <T> CompletableFuture<T> execute(boolean canCancel, boolean hasProgress, boolean isModal, Function<TaskMonitor,CompletableFuture<T>> futureSupplier)
    Similar to `execute(Task)`, but for asynchronous methods
    Type Parameters:
      `T` - the type of future result
    Parameters:
      `canCancel` - true if the task can be cancelled
      `hasProgress` - true if the task displays progress
      `isModal` - true if the task is modal (ignored)
      `futureSupplier` - the task which returns a future, given the task monitor
    Returns:
      the future returned by the supplier