Hi Andrej,

Yes that looks like my first implementation. But then
I reflected that avoiding to map Optional to Duration
and then back to a new Optional containing the same
duration could be avoided by simply storing the original
optional obtained from the HttpClient.

The current code only creates a new instance of Optional
when it needs to.

best regards,

-- daniel

On 18/01/2019 12:42, Andrej Golovnin wrote:
Hi Daniel,

    webrev:
    http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.01/



  126     private static class ConnectTimeoutTracker {
  127         final Optional<Duration> max;
  128         final AtomicLong startTime = new AtomicLong();
  129         ConnectTimeoutTracker(Optional<Duration> connectTimeout) {
  130             this.max = connectTimeout;
  131         }
  132
  133         Optional<Duration> getRemaining() {
  134             if (max.isEmpty()) return max;
  135             long now = System.nanoTime();
  136             long previous = startTime.compareAndExchange(0, now);
  137             if (previous == 0 || max.get().isZero()) return max;
 138             Duration remaining = max.get().minus(Duration.ofNanos(now - previous));
  139             assert remaining.compareTo(max.get()) <= 0;
 140             return Optional.of(remaining.isNegative() ? Duration.ZERO : remaining);
  141         }
  142
  143         void reset() { startTime.set(0); }
  144     }
An Optional in a class field or in a data structure, is considered a misuse of the API (see the explanation by Stuart Marks: https://stackoverflow.com/questions/23454952/uses-for-optional/23464794#23464794). I would write it this way:

       private static class ConnectTimeoutTracker {
           final Duration max;
           final AtomicLong startTime = new AtomicLong();
           ConnectTimeoutTracker(Duration connectTimeout) {
               this.max = connectTimeout;
           }
           Optional<Duration> getRemaining() {
               return Optional.ofNullable(max)
                   .map(m -> {
                       long now = System.nanoTime();
                       long previous = startTime.compareAndExchange(0, now);
                       if (previous == 0 || m.isZero()) {
                           return m;
                       }
                      Duration remaining = m.minus(Duration.ofNanos(now - previous));
                       assert remaining.compareTo(m) <= 0;
                      return remaining.isNegative() ? Duration.ZERO : remaining;
                   });
           }
           void reset() { startTime.set(0); }
       }

Best regards,
Andrej Golovnin

Reply via email to