From f9509694b996c02c140928bf2882b4a4ec96e92f Mon Sep 17 00:00:00 2001 From: Kun Zhang Date: Wed, 31 Jul 2019 11:26:51 -0700 Subject: [PATCH] context: allow creating Deadline with custom Ticker. (#6031) This makes Deadline more test-friendly. Next step is to allow ServerBuilder to take a custom Ticker and use it for creating incoming Deadlines. With both changes in, application logic will be able to verify the Deadlines they set. --- .../test/java/io/grpc/CallOptionsTest.java | 2 +- context/src/main/java/io/grpc/Deadline.java | 55 +++++++++++++++---- .../src/test/java/io/grpc/DeadlineTest.java | 2 +- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/api/src/test/java/io/grpc/CallOptionsTest.java b/api/src/test/java/io/grpc/CallOptionsTest.java index d4ef1fb658..3186130689 100644 --- a/api/src/test/java/io/grpc/CallOptionsTest.java +++ b/api/src/test/java/io/grpc/CallOptionsTest.java @@ -255,7 +255,7 @@ public class CallOptionsTest { private long time; @Override - public long read() { + public long nanoTime() { return time; } diff --git a/context/src/main/java/io/grpc/Deadline.java b/context/src/main/java/io/grpc/Deadline.java index dc091e6c8a..fadbe50874 100644 --- a/context/src/main/java/io/grpc/Deadline.java +++ b/context/src/main/java/io/grpc/Deadline.java @@ -39,7 +39,20 @@ public final class Deadline implements Comparable { private static final long NANOS_PER_SECOND = TimeUnit.SECONDS.toNanos(1); /** - * Create a deadline that will expire at the specified offset from the current system clock. + * Returns the ticker that's based on system clock. + * + *

This is EXPERIMENTAL API and may subject to change. If you'd like it to be + * stabilized or have any feedback, please + * let us know. + */ + public static Ticker getSystemTicker() { + return SYSTEM_TICKER; + } + + /** + * Create a deadline that will expire at the specified offset based on the {@link #getSystemTicker + * system ticker}. + * * @param duration A non-negative duration. * @param units The time unit for the duration. * @return A new deadline. @@ -48,8 +61,19 @@ public final class Deadline implements Comparable { return after(duration, units, SYSTEM_TICKER); } - // For testing - static Deadline after(long duration, TimeUnit units, Ticker ticker) { + /** + * Create a deadline that will expire at the specified offset based on the given {@link Ticker}. + * + *

This is EXPERIMENTAL API and may subject to change. If you'd like it to be + * stabilized or have any feedback, please + * let us know. + * + * @param duration A non-negative duration. + * @param units The time unit for the duration. + * @param ticker Where this deadline refer the current time + * @return A new deadline. + */ + public static Deadline after(long duration, TimeUnit units, Ticker ticker) { checkNotNull(units, "units"); return new Deadline(ticker, units.toNanos(duration), true); } @@ -59,7 +83,7 @@ public final class Deadline implements Comparable { private volatile boolean expired; private Deadline(Ticker ticker, long offset, boolean baseInstantAlreadyExpired) { - this(ticker, ticker.read(), offset, baseInstantAlreadyExpired); + this(ticker, ticker.nanoTime(), offset, baseInstantAlreadyExpired); } private Deadline(Ticker ticker, long baseInstant, long offset, @@ -77,7 +101,7 @@ public final class Deadline implements Comparable { */ public boolean isExpired() { if (!expired) { - if (deadlineNanos - ticker.read() <= 0) { + if (deadlineNanos - ticker.nanoTime() <= 0) { expired = true; } else { return false; @@ -124,7 +148,7 @@ public final class Deadline implements Comparable { * long ago the deadline expired. */ public long timeRemaining(TimeUnit unit) { - final long nowNanos = ticker.read(); + final long nowNanos = ticker.nanoTime(); if (!expired && deadlineNanos - nowNanos <= 0) { expired = true; } @@ -140,7 +164,7 @@ public final class Deadline implements Comparable { public ScheduledFuture runOnExpiration(Runnable task, ScheduledExecutorService scheduler) { checkNotNull(task, "task"); checkNotNull(scheduler, "scheduler"); - return scheduler.schedule(task, deadlineNanos - ticker.read(), TimeUnit.NANOSECONDS); + return scheduler.schedule(task, deadlineNanos - ticker.nanoTime(), TimeUnit.NANOSECONDS); } @Override @@ -173,15 +197,24 @@ public final class Deadline implements Comparable { return 0; } - /** Time source representing nanoseconds since fixed but arbitrary point in time. */ - abstract static class Ticker { + /** + * Time source representing nanoseconds since fixed but arbitrary point in time. + * + *

This is EXPERIMENTAL API and may subject to change. If you'd like it to be + * stabilized or have any feedback, please + * let us know. + * + *

In general implementations should be thread-safe, unless it's implemented and used in a + * localized environment (like unit tests) where you are sure the usages are synchronized. + */ + public abstract static class Ticker { /** Returns the number of nanoseconds since this source's epoch. */ - public abstract long read(); + public abstract long nanoTime(); } private static class SystemTicker extends Ticker { @Override - public long read() { + public long nanoTime() { return System.nanoTime(); } } diff --git a/context/src/test/java/io/grpc/DeadlineTest.java b/context/src/test/java/io/grpc/DeadlineTest.java index d393e68c49..48e172dfd3 100644 --- a/context/src/test/java/io/grpc/DeadlineTest.java +++ b/context/src/test/java/io/grpc/DeadlineTest.java @@ -265,7 +265,7 @@ public class DeadlineTest { private long time; @Override - public long read() { + public long nanoTime() { return time; }