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 long getId() {
84 return id;
85 }
86
87 @Override
88 protected EventExecutor executor() {
89 return super.executor();
90 }
91
92 public long deadlineNanos() {
93 return deadlineNanos;
94 }
95
96 void setConsumed() {
97
98
99 if (periodNanos == 0) {
100 assert scheduledExecutor().getCurrentTimeNanos() >= deadlineNanos;
101 deadlineNanos = 0L;
102 }
103 }
104
105 public long delayNanos() {
106 if (deadlineNanos == 0L) {
107 return 0L;
108 }
109 return delayNanos(scheduledExecutor().getCurrentTimeNanos());
110 }
111
112 static long deadlineToDelayNanos(long currentTimeNanos, long deadlineNanos) {
113 return deadlineNanos == 0L ? 0L : Math.max(0L, deadlineNanos - currentTimeNanos);
114 }
115
116 public long delayNanos(long currentTimeNanos) {
117 return deadlineToDelayNanos(currentTimeNanos, deadlineNanos);
118 }
119
120 @Override
121 public long getDelay(TimeUnit unit) {
122 return unit.convert(delayNanos(), TimeUnit.NANOSECONDS);
123 }
124
125 @Override
126 public int compareTo(Delayed o) {
127 if (this == o) {
128 return 0;
129 }
130
131 ScheduledFutureTask<?> that = (ScheduledFutureTask<?>) o;
132 long d = deadlineNanos() - that.deadlineNanos();
133 if (d < 0) {
134 return -1;
135 } else if (d > 0) {
136 return 1;
137 } else if (id < that.id) {
138 return -1;
139 } else {
140 assert id != that.id;
141 return 1;
142 }
143 }
144
145 @Override
146 public void run() {
147 assert executor().inEventLoop();
148 try {
149 if (delayNanos() > 0L) {
150
151 if (isCancelled()) {
152 scheduledExecutor().scheduledTaskQueue().removeTyped(this);
153 } else {
154 scheduledExecutor().scheduleFromEventLoop(this);
155 }
156 return;
157 }
158 if (periodNanos == 0) {
159 if (setUncancellableInternal()) {
160 V result = runTask();
161 setSuccessInternal(result);
162 }
163 } else {
164
165 if (!isCancelled()) {
166 runTask();
167 if (!executor().isShutdown()) {
168 if (periodNanos > 0) {
169 deadlineNanos += periodNanos;
170 } else {
171 deadlineNanos = scheduledExecutor().getCurrentTimeNanos() - periodNanos;
172 }
173 if (!isCancelled()) {
174 scheduledExecutor().scheduleFromEventLoop(this);
175 }
176 }
177 }
178 }
179 } catch (Throwable cause) {
180 setFailureInternal(cause);
181 }
182 }
183
184 private AbstractScheduledEventExecutor scheduledExecutor() {
185 return (AbstractScheduledEventExecutor) executor();
186 }
187
188
189
190
191
192
193 @Override
194 public boolean cancel(boolean mayInterruptIfRunning) {
195 boolean canceled = super.cancel(mayInterruptIfRunning);
196 if (canceled) {
197 scheduledExecutor().removeScheduled(this);
198 }
199 return canceled;
200 }
201
202 boolean cancelWithoutRemove(boolean mayInterruptIfRunning) {
203 return super.cancel(mayInterruptIfRunning);
204 }
205
206 @Override
207 protected StringBuilder toStringBuilder() {
208 StringBuilder buf = super.toStringBuilder();
209 buf.setCharAt(buf.length() - 1, ',');
210
211 return buf.append(" deadline: ")
212 .append(deadlineNanos)
213 .append(", period: ")
214 .append(periodNanos)
215 .append(')');
216 }
217
218 @Override
219 public int priorityQueueIndex(DefaultPriorityQueue<?> queue) {
220 return queueIndex;
221 }
222
223 @Override
224 public void priorityQueueIndex(DefaultPriorityQueue<?> queue, int i) {
225 queueIndex = i;
226 }
227 }