17
17
*/
18
18
19
19
package org .jpos .space ;
20
+
20
21
import org .jpos .util .Loggeable ;
21
22
import java .io .PrintStream ;
22
23
import java .io .Serializable ;
23
- import java .time .Duration ;
24
- import java .time .Instant ;
25
24
import java .util .*;
26
25
import java .util .concurrent .TimeUnit ;
27
26
@@ -40,8 +39,9 @@ public class TSpace<K,V> implements LocalSpace<K,V>, Loggeable, Runnable {
40
39
private static final long GCLONG = 60 *1000 ;
41
40
private static final long NRD_RESOLUTION = 500L ;
42
41
private static final int MAX_ENTRIES_IN_DUMP = 1000 ;
42
+ private static final long ONE_MILLION = 1_000_000L ; // multiplier millis --> nanos
43
43
private final Set [] expirables ;
44
- private long lastLongGC = Instant . now (). toEpochMilli ();
44
+ private long lastLongGC = System . nanoTime ();
45
45
46
46
public TSpace () {
47
47
super ();
@@ -70,7 +70,7 @@ public void out (K key, V value, long timeout) {
70
70
throw new NullPointerException ("key=" + key + ", value=" + value );
71
71
Object v = value ;
72
72
if (timeout > 0 ) {
73
- v = new Expirable (value , Instant . now (). toEpochMilli () + timeout );
73
+ v = new Expirable (value , System . nanoTime () + ( timeout * ONE_MILLION ) );
74
74
}
75
75
synchronized (this ) {
76
76
List l = getList (key );
@@ -112,17 +112,18 @@ public synchronized V in (Object key) {
112
112
113
113
@ Override
114
114
public synchronized V in (Object key , long timeout ) {
115
- Object obj ;
116
- Instant now = Instant .now ();
117
- long duration ;
118
- while ((obj = inp (key )) == null &&
119
- (duration = Duration .between (now , Instant .now ()).toMillis ()) < timeout )
115
+ V obj ;
116
+ long now = System .nanoTime ();
117
+ long to = now + timeout * ONE_MILLION ;
118
+ long waitFor ;
119
+ while ( (obj = inp (key )) == null &&
120
+ (waitFor = (to - System .nanoTime ())) >= 0 )
120
121
{
121
122
try {
122
- this .wait ( timeout - duration );
123
+ this .wait ( Math . max ( waitFor / ONE_MILLION , 1L ) );
123
124
} catch (InterruptedException e ) { }
124
125
}
125
- return ( V ) obj ;
126
+ return obj ;
126
127
}
127
128
128
129
@ Override
@@ -138,17 +139,18 @@ public synchronized V rd (Object key) {
138
139
139
140
@ Override
140
141
public synchronized V rd (Object key , long timeout ) {
141
- Object obj ;
142
- Instant now = Instant .now ();
143
- long duration ;
144
- while ((obj = rdp (key )) == null &&
145
- (duration = Duration .between (now , Instant .now ()).toMillis ()) < timeout )
142
+ V obj ;
143
+ long now = System .nanoTime ();
144
+ long to = now + (timeout * ONE_MILLION );
145
+ long waitFor ;
146
+ while ( (obj = rdp (key )) == null &&
147
+ (waitFor = (to - System .nanoTime ())) >= 0 )
146
148
{
147
149
try {
148
- this .wait ( timeout - duration );
150
+ this .wait ( Math . max ( waitFor / ONE_MILLION , 1L ) );
149
151
} catch (InterruptedException e ) { }
150
152
}
151
- return ( V ) obj ;
153
+ return obj ;
152
154
}
153
155
154
156
@ Override
@@ -162,17 +164,19 @@ public synchronized void nrd (Object key) {
162
164
163
165
@ Override
164
166
public synchronized V nrd (Object key , long timeout ) {
165
- Object obj ;
166
- Instant now = Instant .now ();
167
- long duration ;
168
- while ((obj = rdp (key )) != null &&
169
- (duration = Duration .between (now , Instant .now ()).toMillis ()) < timeout )
167
+ V obj ;
168
+ long now = System .nanoTime ();
169
+ long to = now + (timeout * ONE_MILLION );
170
+ long waitFor ;
171
+ while ( (obj = rdp (key )) != null &&
172
+ (waitFor = (to - System .nanoTime ())) >= 0 )
170
173
{
171
174
try {
172
- this .wait (Math .min (NRD_RESOLUTION , timeout - duration ));
175
+ this .wait (Math .min (NRD_RESOLUTION ,
176
+ Math .max (waitFor / ONE_MILLION , 1L )));
173
177
} catch (InterruptedException ignored ) { }
174
178
}
175
- return ( V ) obj ;
179
+ return obj ;
176
180
}
177
181
178
182
@ Override
@@ -186,9 +190,9 @@ public void run () {
186
190
187
191
public void gc () {
188
192
gc (0 );
189
- if (Instant . now (). toEpochMilli () - lastLongGC > GCLONG ) {
193
+ if (System . nanoTime () - lastLongGC > GCLONG ) {
190
194
gc (1 );
191
- lastLongGC = Instant . now (). toEpochMilli ();
195
+ lastLongGC = System . nanoTime ();
192
196
}
193
197
}
194
198
@@ -336,7 +340,7 @@ public void push (K key, V value, long timeout) {
336
340
throw new NullPointerException ("key=" + key + ", value=" + value );
337
341
Object v = value ;
338
342
if (timeout > 0 ) {
339
- v = new Expirable (value , Instant . now (). toEpochMilli () + timeout );
343
+ v = new Expirable (value , System . nanoTime () + ( timeout * ONE_MILLION ) );
340
344
}
341
345
synchronized (this ) {
342
346
List l = getList (key );
@@ -373,7 +377,7 @@ public void put (K key, V value, long timeout) {
373
377
throw new NullPointerException ("key=" + key + ", value=" + value );
374
378
Object v = value ;
375
379
if (timeout > 0 ) {
376
- v = new Expirable (value , Instant . now (). toEpochMilli () + timeout );
380
+ v = new Expirable (value , System . nanoTime () + ( timeout * ONE_MILLION ) );
377
381
}
378
382
synchronized (this ) {
379
383
List l = new LinkedList ();
@@ -399,14 +403,15 @@ public boolean existAny (K[] keys) {
399
403
400
404
@ Override
401
405
public boolean existAny (K [] keys , long timeout ) {
402
- Instant now = Instant .now ();
403
- long duration ;
404
- while ((duration = Duration .between (now , Instant .now ()).toMillis ()) < timeout ) {
406
+ long now = System .nanoTime ();
407
+ long to = now + (timeout * ONE_MILLION );
408
+ long waitFor ;
409
+ while ((waitFor = (to - System .nanoTime ())) >= 0 ) {
405
410
if (existAny (keys ))
406
411
return true ;
407
412
synchronized (this ) {
408
413
try {
409
- wait ( timeout - duration );
414
+ this . wait ( Math . max ( waitFor / ONE_MILLION , 1L ) );
410
415
} catch (InterruptedException e ) { }
411
416
}
412
417
}
@@ -517,19 +522,24 @@ private void unregisterExpirable(Object k) {
517
522
518
523
static class Expirable implements Comparable , Serializable {
519
524
520
- static final long serialVersionUID = 0xA7F22BF5 ;
525
+ private static final long serialVersionUID = 0xA7F22BF5 ;
521
526
522
527
Object value ;
528
+
529
+ /**
530
+ * When to expire, in the future, as given by monotonic System.nanoTime().<br>
531
+ * IMPORTANT: always use a nanosec offset from System.nanoTime()!
532
+ */
523
533
long expires ;
524
534
525
- public Expirable (Object value , long expires ) {
535
+ Expirable (Object value , long expires ) {
526
536
super ();
527
537
this .value = value ;
528
538
this .expires = expires ;
529
539
}
530
540
531
- public boolean isExpired () {
532
- return expires < Instant . now (). toEpochMilli () ;
541
+ boolean isExpired () {
542
+ return ( System . nanoTime () - expires ) > 0 ;
533
543
}
534
544
535
545
@ Override
@@ -540,20 +550,16 @@ public String toString() {
540
550
+ ",expired=" + isExpired ();
541
551
}
542
552
543
- public Object getValue () {
553
+ Object getValue () {
544
554
return isExpired () ? null : value ;
545
555
}
546
556
547
557
@ Override
548
- public int compareTo (Object obj ) {
549
- Expirable other = (Expirable ) obj ;
550
- long otherExpires = other .expires ;
551
- if (otherExpires == expires )
552
- return 0 ;
553
- else if (expires < otherExpires )
554
- return -1 ;
555
- else
556
- return 1 ;
558
+ public int compareTo (Object other ) {
559
+ long diff = this .expires - ((Expirable )other ).expires ;
560
+ return diff > 0 ? 1 :
561
+ diff < 0 ? -1 :
562
+ 0 ;
557
563
}
558
564
}
559
565
0 commit comments