1717 */
1818
1919package org .jpos .space ;
20+
2021import org .jpos .util .Loggeable ;
2122import java .io .PrintStream ;
2223import java .io .Serializable ;
23- import java .time .Duration ;
24- import java .time .Instant ;
2524import java .util .*;
2625import java .util .concurrent .TimeUnit ;
2726
@@ -40,8 +39,9 @@ public class TSpace<K,V> implements LocalSpace<K,V>, Loggeable, Runnable {
4039 private static final long GCLONG = 60 *1000 ;
4140 private static final long NRD_RESOLUTION = 500L ;
4241 private static final int MAX_ENTRIES_IN_DUMP = 1000 ;
42+ private static final long ONE_MILLION = 1_000_000L ; // multiplier millis --> nanos
4343 private final Set [] expirables ;
44- private long lastLongGC = Instant . now (). toEpochMilli ();
44+ private long lastLongGC = System . nanoTime ();
4545
4646 public TSpace () {
4747 super ();
@@ -70,7 +70,7 @@ public void out (K key, V value, long timeout) {
7070 throw new NullPointerException ("key=" + key + ", value=" + value );
7171 Object v = value ;
7272 if (timeout > 0 ) {
73- v = new Expirable (value , Instant . now (). toEpochMilli () + timeout );
73+ v = new Expirable (value , System . nanoTime () + ( timeout * ONE_MILLION ) );
7474 }
7575 synchronized (this ) {
7676 List l = getList (key );
@@ -112,17 +112,18 @@ public synchronized V in (Object key) {
112112
113113 @ Override
114114 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 )
120121 {
121122 try {
122- this .wait ( timeout - duration );
123+ this .wait ( Math . max ( waitFor / ONE_MILLION , 1L ) );
123124 } catch (InterruptedException e ) { }
124125 }
125- return ( V ) obj ;
126+ return obj ;
126127 }
127128
128129 @ Override
@@ -138,17 +139,18 @@ public synchronized V rd (Object key) {
138139
139140 @ Override
140141 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 )
146148 {
147149 try {
148- this .wait ( timeout - duration );
150+ this .wait ( Math . max ( waitFor / ONE_MILLION , 1L ) );
149151 } catch (InterruptedException e ) { }
150152 }
151- return ( V ) obj ;
153+ return obj ;
152154 }
153155
154156 @ Override
@@ -162,17 +164,19 @@ public synchronized void nrd (Object key) {
162164
163165 @ Override
164166 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 )
170173 {
171174 try {
172- this .wait (Math .min (NRD_RESOLUTION , timeout - duration ));
175+ this .wait (Math .min (NRD_RESOLUTION ,
176+ Math .max (waitFor / ONE_MILLION , 1L )));
173177 } catch (InterruptedException ignored ) { }
174178 }
175- return ( V ) obj ;
179+ return obj ;
176180 }
177181
178182 @ Override
@@ -186,9 +190,9 @@ public void run () {
186190
187191 public void gc () {
188192 gc (0 );
189- if (Instant . now (). toEpochMilli () - lastLongGC > GCLONG ) {
193+ if (System . nanoTime () - lastLongGC > GCLONG ) {
190194 gc (1 );
191- lastLongGC = Instant . now (). toEpochMilli ();
195+ lastLongGC = System . nanoTime ();
192196 }
193197 }
194198
@@ -336,7 +340,7 @@ public void push (K key, V value, long timeout) {
336340 throw new NullPointerException ("key=" + key + ", value=" + value );
337341 Object v = value ;
338342 if (timeout > 0 ) {
339- v = new Expirable (value , Instant . now (). toEpochMilli () + timeout );
343+ v = new Expirable (value , System . nanoTime () + ( timeout * ONE_MILLION ) );
340344 }
341345 synchronized (this ) {
342346 List l = getList (key );
@@ -373,7 +377,7 @@ public void put (K key, V value, long timeout) {
373377 throw new NullPointerException ("key=" + key + ", value=" + value );
374378 Object v = value ;
375379 if (timeout > 0 ) {
376- v = new Expirable (value , Instant . now (). toEpochMilli () + timeout );
380+ v = new Expirable (value , System . nanoTime () + ( timeout * ONE_MILLION ) );
377381 }
378382 synchronized (this ) {
379383 List l = new LinkedList ();
@@ -399,14 +403,15 @@ public boolean existAny (K[] keys) {
399403
400404 @ Override
401405 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 ) {
405410 if (existAny (keys ))
406411 return true ;
407412 synchronized (this ) {
408413 try {
409- wait ( timeout - duration );
414+ this . wait ( Math . max ( waitFor / ONE_MILLION , 1L ) );
410415 } catch (InterruptedException e ) { }
411416 }
412417 }
@@ -517,19 +522,24 @@ private void unregisterExpirable(Object k) {
517522
518523 static class Expirable implements Comparable , Serializable {
519524
520- static final long serialVersionUID = 0xA7F22BF5 ;
525+ private static final long serialVersionUID = 0xA7F22BF5 ;
521526
522527 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+ */
523533 long expires ;
524534
525- public Expirable (Object value , long expires ) {
535+ Expirable (Object value , long expires ) {
526536 super ();
527537 this .value = value ;
528538 this .expires = expires ;
529539 }
530540
531- public boolean isExpired () {
532- return expires < Instant . now (). toEpochMilli () ;
541+ boolean isExpired () {
542+ return ( System . nanoTime () - expires ) > 0 ;
533543 }
534544
535545 @ Override
@@ -540,20 +550,16 @@ public String toString() {
540550 + ",expired=" + isExpired ();
541551 }
542552
543- public Object getValue () {
553+ Object getValue () {
544554 return isExpired () ? null : value ;
545555 }
546556
547557 @ 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 ;
557563 }
558564 }
559565
0 commit comments