1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.util.concurrent;
18
19 import java.util.Queue;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.Delayed;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.atomic.AtomicLong;
24
25 @SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
26 final class ScheduledFutureTask<V> extends PromiseTask<V> implements ScheduledFuture<V> {
27 private static final AtomicLong nextTaskId = new AtomicLong();
28 private static final long START_TIME = System.nanoTime();
29
30 static long nanoTime() {
31 return System.nanoTime() - START_TIME;
32 }
33
34 static long deadlineNanos(long delay) {
35 return nanoTime() + delay;
36 }
37
38 private final long id = nextTaskId.getAndIncrement();
39 private long deadlineNanos;
40
41 private final long periodNanos;
42
43 ScheduledFutureTask(
44 AbstractScheduledEventExecutor executor,
45 Runnable runnable, V result, long nanoTime) {
46
47 this(executor, toCallable(runnable, result), nanoTime);
48 }
49
50 ScheduledFutureTask(
51 AbstractScheduledEventExecutor executor,
52 Callable<V> callable, long nanoTime, long period) {
53
54 super(executor, callable);
55 if (period == 0) {
56 throw new IllegalArgumentException("period: 0 (expected: != 0)");
57 }
58 deadlineNanos = nanoTime;
59 periodNanos = period;
60 }
61
62 ScheduledFutureTask(
63 AbstractScheduledEventExecutor executor,
64 Callable<V> callable, long nanoTime) {
65
66 super(executor, callable);
67 deadlineNanos = nanoTime;
68 periodNanos = 0;
69 }
70
71 @Override
72 protected EventExecutor executor() {
73 return super.executor();
74 }
75
76 public long deadlineNanos() {
77 return deadlineNanos;
78 }
79
80 public long delayNanos() {
81 return Math.max(0, deadlineNanos() - nanoTime());
82 }
83
84 public long delayNanos(long currentTimeNanos) {
85 return Math.max(0, deadlineNanos() - (currentTimeNanos - START_TIME));
86 }
87
88 @Override
89 public long getDelay(TimeUnit unit) {
90 return unit.convert(delayNanos(), TimeUnit.NANOSECONDS);
91 }
92
93 @Override
94 public int compareTo(Delayed o) {
95 if (this == o) {
96 return 0;
97 }
98
99 ScheduledFutureTask<?> that = (ScheduledFutureTask<?>) o;
100 long d = deadlineNanos() - that.deadlineNanos();
101 if (d < 0) {
102 return -1;
103 } else if (d > 0) {
104 return 1;
105 } else if (id < that.id) {
106 return -1;
107 } else if (id == that.id) {
108 throw new Error();
109 } else {
110 return 1;
111 }
112 }
113
114 @Override
115 public void run() {
116 assert executor().inEventLoop();
117 try {
118 if (periodNanos == 0) {
119 if (setUncancellableInternal()) {
120 V result = task.call();
121 setSuccessInternal(result);
122 }
123 } else {
124
125 if (!isCancelled()) {
126 task.call();
127 if (!executor().isShutdown()) {
128 long p = periodNanos;
129 if (p > 0) {
130 deadlineNanos += p;
131 } else {
132 deadlineNanos = nanoTime() - p;
133 }
134 if (!isCancelled()) {
135
136 Queue<ScheduledFutureTask<?>> scheduledTaskQueue =
137 ((AbstractScheduledEventExecutor) executor()).scheduledTaskQueue;
138 assert scheduledTaskQueue != null;
139 scheduledTaskQueue.add(this);
140 }
141 }
142 }
143 }
144 } catch (Throwable cause) {
145 setFailureInternal(cause);
146 }
147 }
148
149
150
151
152
153
154 @Override
155 public boolean cancel(boolean mayInterruptIfRunning) {
156 boolean canceled = super.cancel(mayInterruptIfRunning);
157 if (canceled) {
158 ((AbstractScheduledEventExecutor) executor()).removeScheduled(this);
159 }
160 return canceled;
161 }
162
163 boolean cancelWithoutRemove(boolean mayInterruptIfRunning) {
164 return super.cancel(mayInterruptIfRunning);
165 }
166
167 @Override
168 protected StringBuilder toStringBuilder() {
169 StringBuilder buf = super.toStringBuilder();
170 buf.setCharAt(buf.length() - 1, ',');
171
172 return buf.append(" id: ")
173 .append(id)
174 .append(", deadline: ")
175 .append(deadlineNanos)
176 .append(", period: ")
177 .append(periodNanos)
178 .append(')');
179 }
180 }