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 Futures are not CompletableFutures. 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.

  • Field Details

  • 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