@@ -31,6 +31,16 @@ class Selector[A](api: GopherAPI) extends PromiseFlowTermination[A]
31
31
idleWaiters add makeLocked(Skip (f,this ))
32
32
}
33
33
34
+ def addTimeoutSkip (f : Skip [A ] => Option [Future [Continuated [A ]]], timeout : FiniteDuration ): Unit =
35
+ {
36
+ if (timeoutRecord.isEmpty) {
37
+ val locked = makeLocked(Skip (f,this ))
38
+ timeoutRecord = Some (new TimeoutRecord (nOperations.get,timeout.toMillis,locked))
39
+ } else {
40
+ throw new IllegalStateException (" select must have only one timeout entry" )
41
+ }
42
+ }
43
+
34
44
def run : Future [A ] =
35
45
{
36
46
sendWaits()
@@ -130,6 +140,33 @@ class Selector[A](api: GopherAPI) extends PromiseFlowTermination[A]
130
140
}
131
141
132
142
143
+ private [this ] def scheduleTimeout (): Unit =
144
+ {
145
+
146
+ val scheduler = api.actorSystem.scheduler
147
+
148
+ def tickOperation (): Unit =
149
+ {
150
+ if (! isCompleted) {
151
+ for (tr <- timeoutRecord) {
152
+ val currentNOperations = nOperations.get()
153
+ if (currentNOperations == tr.lastNOperations) {
154
+ // fire
155
+ ???
156
+ } else {
157
+ val now = System .currentTimeMillis()
158
+ val nextTime = lastOperationEnd.get() + tr.timeoutMillis
159
+ tr.lastNOperations = nOperations.get()
160
+ scheduler.scheduleOnce((nextTime - now).millis)(tickOperation)
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ tickOperation()
167
+
168
+ }
169
+
133
170
def isLocked : Boolean = lockFlag.get();
134
171
135
172
private [this ] def tryLock (): Boolean = lockFlag.compareAndSet(false ,true )
@@ -156,6 +193,8 @@ class Selector[A](api: GopherAPI) extends PromiseFlowTermination[A]
156
193
} else true
157
194
}
158
195
196
+
197
+
159
198
private [this ] def sendWaits (waiters : ConcurrentLinkedQueue [Continuated [A ]] = waiters): Unit =
160
199
{
161
200
// concurrent structure fpr priority queue
@@ -184,10 +223,13 @@ class Selector[A](api: GopherAPI) extends PromiseFlowTermination[A]
184
223
}
185
224
}
186
225
187
-
188
226
189
227
// false when unlocked, true otherwise.
190
228
private [this ] val lockFlag : AtomicBoolean = new AtomicBoolean (false )
229
+
230
+ // when last operation was started
231
+ private [this ] val lastOperationEnd : AtomicLong = new AtomicLong (0L )
232
+ private [this ] var haveTimeout : Boolean = false
191
233
192
234
// number of operations, increased during each lock/unlock.
193
235
// used for idle detection.
@@ -196,6 +238,13 @@ class Selector[A](api: GopherAPI) extends PromiseFlowTermination[A]
196
238
private [this ] val waiters : ConcurrentLinkedQueue [Continuated [A ]] = new ConcurrentLinkedQueue ()
197
239
private [this ] val idleWaiters : ConcurrentLinkedQueue [Continuated [A ]] = new ConcurrentLinkedQueue ()
198
240
241
+ private [this ] class TimeoutRecord (
242
+ var lastNOperations : Long ,
243
+ var timeoutMillis : Long ,
244
+ var waiter : Continuated [A ]
245
+ )
246
+ private [this ] var timeoutRecord : Option [TimeoutRecord ] = None
247
+
199
248
private [this ] val processor = api.continuatedProcessorRef
200
249
201
250
private [this ] implicit val executionContext : ExecutionContext = api.executionContext
0 commit comments