1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.concurrency.IdleTimeout;
13 
14 
15 /**
16  * An Abstract implementation of an Idle Timeout.
17  * <p>
18  * This implementation is optimised that timeout operations are not cancelled on
19  * every operation. Rather timeout are allowed to expire and a check is then
20  * made to see when the last operation took place. If the idle timeout has not
21  * expired, the timeout is rescheduled for the earliest possible time a timeout
22  * could occur.
23  */
24 // abstract class IdleTimeout {
25 //     private final Scheduler scheduler;
26 //     private final AtomicReference<Scheduler.Future> timeout = new AtomicReference<>();
27 //     private long idleTimeout;
28 //     private long idleTimestamp = Millisecond100Clock.currentTimeMillis();
29 
30 //     private final Runnable idleTask = new Runnable() {
31 //         override
32 //         void run() {
33 //             long idleLeft = checkIdleTimeout();
34 //             if (idleLeft >= 0)
35 //                 scheduleIdleTimeout(idleLeft > 0 ? idleLeft : getIdleTimeout());
36 //         }
37 //     };
38 
39 //     /**
40 //      * @param scheduler A scheduler used to schedule checks for the idle timeout.
41 //      */
42 //     IdleTimeout(Scheduler scheduler) {
43 //         this.scheduler = scheduler;
44 //     }
45 
46 //     Scheduler getScheduler() {
47 //         return scheduler;
48 //     }
49 
50 //     long getIdleTimestamp() {
51 //         return idleTimestamp;
52 //     }
53 
54 //     long getIdleFor() {
55 //         return Millisecond100Clock.currentTimeMillis() - getIdleTimestamp();
56 //     }
57 
58 //     long getIdleTimeout() {
59 //         return idleTimeout;
60 //     }
61 
62 //     void setIdleTimeout(long idleTimeout) {
63 //         long old = this.idleTimeout;
64 //         this.idleTimeout = idleTimeout;
65 
66 //         // Do we have an old timeout
67 //         if (old > 0) {
68 //             // if the old was less than or equal to the new timeout, then
69 //             // nothing more to do
70 //             if (old <= idleTimeout)
71 //                 return;
72 
73 //             // old timeout is too long, so cancel it.
74 //             deactivate();
75 //         }
76 
77 //         // If we have a new timeout, then check and reschedule
78 //         if (isOpen())
79 //             activate();
80 //     }
81 
82 //     /**
83 //      * This method should be called when non-idle activity has taken place.
84 //      */
85 //     void notIdle() {
86 //         idleTimestamp = Millisecond100Clock.currentTimeMillis();
87 //     }
88 
89 //     private void scheduleIdleTimeout(long delay) {
90 //         Scheduler.Future newTimeout = null;
91 //         if (isOpen() && delay > 0 && scheduler !is null)
92 //             newTimeout = scheduler.schedule(idleTask, delay, TimeUnit.MILLISECONDS);
93 //         Scheduler.Future oldTimeout = timeout.getAndSet(newTimeout);
94 //         if (oldTimeout !is null)
95 //             oldTimeout.cancel();
96 //     }
97 
98 //     void onOpen() {
99 //         activate();
100 //     }
101 
102 //     private void activate() {
103 //         if (idleTimeout > 0)
104 //             idleTask.run();
105 //     }
106 
107 //     void onClose() {
108 //         deactivate();
109 //     }
110 
111 //     private void deactivate() {
112 //         Scheduler.Future oldTimeout = timeout.getAndSet(null);
113 //         if (oldTimeout !is null)
114 //             oldTimeout.cancel();
115 //     }
116 
117 //     protected long checkIdleTimeout() {
118 //         if (isOpen()) {
119 //             long idleTimestamp = getIdleTimestamp();
120 //             long idleTimeout = getIdleTimeout();
121 //             long idleElapsed = Millisecond100Clock.currentTimeMillis() - idleTimestamp;
122 //             long idleLeft = idleTimeout - idleElapsed;
123 
124 //             // System.out.println("{} idle timeout check, elapsed: {} ms,
125 //             // remaining: {} ms", this, idleElapsed, idleLeft);
126 
127 //             if (idleTimestamp != 0 && idleTimeout > 0) {
128 //                 if (idleLeft <= 0) {
129 
130 //                     // System.out.println("{} idle timeout expired", this);
131 //                     try {
132 //                         onIdleExpired(new TimeoutException(
133 //                                 "Idle timeout expired: " ~ idleElapsed ~ "/" ~ idleTimeout ~ " ms"));
134 //                     } finally {
135 //                         notIdle();
136 //                     }
137 //                 }
138 //             }
139 
140 //             return idleLeft >= 0 ? idleLeft : 0;
141 //         }
142 //         return -1;
143 //     }
144 
145 //     /**
146 //      * This abstract method is called when the idle timeout has expired.
147 //      *
148 //      * @param timeout a TimeoutException
149 //      */
150 //     protected abstract void onIdleExpired(TimeoutException timeout);
151 
152 //     /**
153 //      * This abstract method should be called to check if idle timeouts should
154 //      * still be checked.
155 //      *
156 //      * @return True if the entity monitored should still be checked for idle
157 //      * timeouts
158 //      */
159 //     abstract bool isOpen();
160 // }