1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.util.concurrent;
17
18 import java.util.Collections;
19 import java.util.IdentityHashMap;
20 import java.util.Set;
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.atomic.AtomicLong;
23 import java.util.concurrent.locks.Condition;
24 import java.util.concurrent.locks.ReentrantLock;
25
26 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
27 import static java.util.Objects.requireNonNull;
28
29
30
31
32 final class DefaultMockTicker implements MockTicker {
33
34
35 private final ReentrantLock lock = new ReentrantLock(true);
36 private final Condition tickCondition = lock.newCondition();
37 private final Condition sleeperCondition = lock.newCondition();
38 private final AtomicLong nanoTime = new AtomicLong();
39 private final Set<Thread> sleepers = Collections.newSetFromMap(new IdentityHashMap<>());
40
41 @Override
42 public long nanoTime() {
43 return nanoTime.get();
44 }
45
46 @Override
47 public void sleep(long delay, TimeUnit unit) throws InterruptedException {
48 checkPositiveOrZero(delay, "delay");
49 requireNonNull(unit, "unit");
50
51 if (delay == 0) {
52 return;
53 }
54
55 final long delayNanos = unit.toNanos(delay);
56 lock.lockInterruptibly();
57 try {
58 final long startTimeNanos = nanoTime();
59 sleepers.add(Thread.currentThread());
60 sleeperCondition.signalAll();
61 do {
62 tickCondition.await();
63 } while (nanoTime() - startTimeNanos < delayNanos);
64 } finally {
65 sleepers.remove(Thread.currentThread());
66 lock.unlock();
67 }
68 }
69
70
71
72
73 public void awaitSleepingThread(Thread thread) throws InterruptedException {
74 lock.lockInterruptibly();
75 try {
76 while (!sleepers.contains(thread)) {
77 sleeperCondition.await();
78 }
79 } finally {
80 lock.unlock();
81 }
82 }
83
84 @Override
85 public void advance(long amount, TimeUnit unit) {
86 checkPositiveOrZero(amount, "amount");
87 requireNonNull(unit, "unit");
88
89 if (amount == 0) {
90 return;
91 }
92
93 final long amountNanos = unit.toNanos(amount);
94 lock.lock();
95 try {
96 nanoTime.addAndGet(amountNanos);
97 tickCondition.signalAll();
98 } finally {
99 lock.unlock();
100 }
101 }
102 }
103