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 io.netty.util.internal.DefaultPriorityQueue;
20 import io.netty.util.internal.PriorityQueueNode;
21
22 import java.util.concurrent.Callable;
23 import java.util.concurrent.Delayed;
24 import java.util.concurrent.TimeUnit;
25
26 @SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
27 final class ScheduledFutureTask<V> extends PromiseTask<V> implements ScheduledFuture<V>, PriorityQueueNode {
28
29 private long id;
30
31 private long deadlineNanos;
32
33 private final long periodNanos;
34
35 private int queueIndex = INDEX_NOT_IN_QUEUE;
36
37 ScheduledFutureTask(AbstractScheduledEventExecutor executor,
38 Runnable runnable, long nanoTime) {
39
40 super(executor, runnable);
41 deadlineNanos = nanoTime;
42 periodNanos = 0;
43 }
44
45 ScheduledFutureTask(AbstractScheduledEventExecutor executor,
46 Runnable runnable, long nanoTime, long period) {
47
48 super(executor, runnable);
49 deadlineNanos = nanoTime;
50 periodNanos = validatePeriod(period);
51 }
52
53 ScheduledFutureTask(AbstractScheduledEventExecutor executor,
54 Callable<V> callable, long nanoTime, long period) {
55
56 super(executor, callable);
57 deadlineNanos = nanoTime;
58 periodNanos = validatePeriod(period);
59 }
60
61 ScheduledFutureTask(AbstractScheduledEventExecutor executor,
62 Callable<V> callable, long nanoTime) {
63
64 super(executor, callable);
65 deadlineNanos = nanoTime;
66 periodNanos = 0;
67 }
68
69 private static long validatePeriod(long period) {
70 if (period == 0) {
71 throw new IllegalArgumentException("period: 0 (expected: != 0)");
72 }
73 return period;
74 }
75
76 ScheduledFutureTask<V> setId(long id) {
77 if (this.id == 0L) {
78 this.id = id;
79 }
80 return this;
81 }
82
83 @Override
84 protected EventExecutor executor() {
85 return super.executor();
86 }
87
88 public long deadlineNanos() {
89 return deadlineNanos;
90 }
91
92 void setConsumed() {
93
94
95 if (periodNanos == 0) {
96 assert scheduledExecutor().getCurrentTimeNanos() >= deadlineNanos;
97 deadlineNanos = 0L;
98 }
99 }
100
101 public long delayNanos() {
102 if (deadlineNanos == 0L) {
103 return 0L;
104 }
105 return delayNanos(scheduledExecutor().getCurrentTimeNanos());
106 }
107
108 static long deadlineToDelayNanos(long currentTimeNanos, long deadlineNanos) {
109 return deadlineNanos == 0L ? 0L : Math.max(0L, deadlineNanos - currentTimeNanos);
110 }
111
112 public long delayNanos(long currentTimeNanos) {
113 return deadlineToDelayNanos(currentTimeNanos, deadlineNanos);
114 }
115
116 @Override
117 public long getDelay(TimeUnit unit) {
118 return unit.convert(delayNanos(), TimeUnit.NANOSECONDS);
119 }
120
121 @Override
122 public int compareTo(Delayed o) {
123 if (this == o) {
124 return 0;
125 }
126
127 ScheduledFutureTask<?> that = (ScheduledFutureTask<?>) o;
128 long d = deadlineNanos() - that.deadlineNanos();
129 if (d < 0) {
130 return -1;
131 } else if (d > 0) {
132 return 1;
133 } else if (id < that.id) {
134 return -1;
135 } else {
136 assert id != that.id;
137 return 1;
138 }
139 }
140
141 @Override
142 public void run() {
143 assert executor().inEventLoop();
144 try {
145 if (delayNanos() > 0L) {
146
147 if (isCancelled()) {
148 scheduledExecutor().scheduledTaskQueue().removeTyped(this);
149 } else {
150 scheduledExecutor().scheduleFromEventLoop(this);
151 }
152 return;
153 }
154 if (periodNanos == 0) {
155 if (setUncancellableInternal()) {
156 V result = runTask();
157 setSuccessInternal(result);
158 }
159 } else {
160
161 if (!isCancelled()) {
162 runTask();
163 if (!executor().isShutdown()) {
164 if (periodNanos > 0) {
165 deadlineNanos += periodNanos;
166 } else {
167 deadlineNanos = scheduledExecutor().getCurrentTimeNanos() - periodNanos;
168 }
169 if (!isCancelled()) {
170 scheduledExecutor().scheduledTaskQueue().add(this);
171 }
172 }
173 }
174 }
175 } catch (Throwable cause) {
176 setFailureInternal(cause);
177 }
178 }
179
180 private AbstractScheduledEventExecutor scheduledExecutor() {
181 return (AbstractScheduledEventExecutor) executor();
182 }
183
184
185
186
187
188
189 @Override
190 public boolean cancel(boolean mayInterruptIfRunning) {
191 boolean canceled = super.cancel(mayInterruptIfRunning);
192 if (canceled) {
193 scheduledExecutor().removeScheduled(this);
194 }
195 return canceled;
196 }
197
198 boolean cancelWithoutRemove(boolean mayInterruptIfRunning) {
199 return super.cancel(mayInterruptIfRunning);
200 }
201
202 @Override
203 protected StringBuilder toStringBuilder() {
204 StringBuilder buf = super.toStringBuilder();
205 buf.setCharAt(buf.length() - 1, ',');
206
207 return buf.append(" deadline: ")
208 .append(deadlineNanos)
209 .append(", period: ")
210 .append(periodNanos)
211 .append(')');
212 }
213
214 @Override
215 public int priorityQueueIndex(DefaultPriorityQueue<?> queue) {
216 return queueIndex;
217 }
218
219 @Override
220 public void priorityQueueIndex(DefaultPriorityQueue<?> queue, int i) {
221 queueIndex = i;
222 }
223 }