Package ghidra.async

# Class AsyncTimer

java.lang.Object
ghidra.async.AsyncTimer

public class AsyncTimer extends Object
A timer for asynchronous scheduled tasks

This object provides a futures which complete at specified times. This is useful for pausing amid a chain of callback actions, i.e., between iterations of a loop. A critical tenant of asynchronous reactive programming is to never block a thread, at least not for an indefinite period of time. If an action blocks, it may prevent completion of other tasks in its executor's queue, possibly resulting in deadlock. An easy and tempting way to accidentally block is to call `Object.wait()` or `Thread.sleep(long)` when trying to wait for a specific period of time. Unfortunately, this does not just block the chain, but blocks the thread. Java provides a `Timer`, but its `Future`s are not `CompletableFuture`s. The same is true of `ScheduledThreadPoolExecutor`.

A delay is achieved using `mark()`, then `AsyncTimer.Mark.after(long)`.

     future.thenCompose(__ -> timer.mark().after(1000))

`mark()` marks the current system time; all calls to the mark's `AsyncTimer.Mark.after(long)` schedule futures relative to this mark. Scheduling a timed sequence of actions is best accomplished using times relative to a single mark. For example:

     Mark mark = timer.mark();
     mark.after(1000).thenCompose(__ -> {
            doTaskAtOneSecond();
            return mark.after(2000);
     }).thenAccept(__ -> {
            doTaskAtTwoSeconds();
     });

This provides slightly more precise scheduling than delaying for a fixed period between tasks. Consider a second example:

Like `Timer`, each `AsyncTimer` is backed by a single thread which uses `Object.wait()` to implement its timing. Thus, this is not suitable for real-time applications. Unlike `Timer`, the backing thread is always a daemon. It will not prevent process termination. If a task is long running, the sequence should queue it on another executor, perhaps using `CompletableFuture.supplyAsync(Supplier, Executor)`. Otherwise, other scheduled tasks may be inordinately delayed.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `class`
  `AsyncTimer.Mark`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final AsyncTimer`
  `DEFAULT_TIMER`
  `protected ExecutorService`
  `thread`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `AsyncTimer()`
  Create a new timer

- ## Method Summary

  Modifier and Type
  Method
  Description
  `CompletableFuture<Void>`
  `atSystemTime(long timeMillis)`
  Schedule a task to run when `System.currentTimeMillis()` has passed a given time
  `AsyncTimer.Mark`
  `mark()`
  Mark the current system time

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### DEFAULT_TIMER

    public static final AsyncTimer DEFAULT_TIMER

  - ### thread

    protected ExecutorService thread

- ## Constructor Details

  - ### AsyncTimer

    public AsyncTimer()
    Create a new timer

    Except to reduce contention among threads, most applications need only create one timer instance. See `DEFAULT_TIMER`.

- ## Method Details

  - ### atSystemTime

    public CompletableFuture<Void> atSystemTime(long timeMillis)
    Schedule a task to run when `System.currentTimeMillis()` has passed a given time

    This method returns immediately, giving a future result. The future completes "soon after" the current system time passes the given time in milliseconds. There is some minimal overhead, but the scheduler endeavors to complete the future as close to the given time as possible. The actual scheduled time will not precede the requested time.

    Parameters:
      `timeMillis` - the time after which the returned future completes
    Returns:
      a future that completes soon after the given time

  - ### mark

    public AsyncTimer.Mark mark()
    Mark the current system time
    Returns:
      this same timer