2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.util;
10 import com.google.common.primitives.UnsignedLong;
11 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
12 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
15 * Concurrent version of {@link DurationStatisticsTracker}.
17 // TODO: once DurationStatsTracker is gone make this class final
18 class ConcurrentDurationStatisticsTracker extends DurationStatisticsTracker {
19 private static final AtomicReferenceFieldUpdater<ConcurrentDurationStatisticsTracker, DurationWithTime> LONGEST_UPDATER =
20 AtomicReferenceFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, DurationWithTime.class, "longest");
21 private static final AtomicReferenceFieldUpdater<ConcurrentDurationStatisticsTracker, DurationWithTime> SHORTEST_UPDATER =
22 AtomicReferenceFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, DurationWithTime.class, "shortest");
23 private static final AtomicLongFieldUpdater<ConcurrentDurationStatisticsTracker> COUNT_UPDATER =
24 AtomicLongFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, "count");
25 private static final AtomicLongFieldUpdater<ConcurrentDurationStatisticsTracker> SUM_UPDATER =
26 AtomicLongFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, "sum");
28 private volatile long sum = 0;
29 private volatile long count = 0;
30 private volatile DurationWithTime longest = null;
31 private volatile DurationWithTime shortest = null;
33 ConcurrentDurationStatisticsTracker() {
38 public final void addDuration(final long duration) {
39 // First update the quick stats
40 SUM_UPDATER.addAndGet(this, duration);
41 COUNT_UPDATER.incrementAndGet(this);
44 * Now the hairy 'min/max' things. The notion of "now" we cache,
45 * so the first time we use it, we do not call it twice. We populate
48 * The longest/shortest stats both are encapsulated in an object,
49 * so we update them atomically and we minimize the number of volatile
52 DurationWithTime current = shortest;
53 if (current == null || duration < current.getDuration()) {
54 final DurationWithTime newObj = new DurationWithTime(duration, System.currentTimeMillis());
55 while (!SHORTEST_UPDATER.weakCompareAndSet(this, current, newObj)) {
57 if (current != null && duration >= current.getDuration()) {
64 if (current == null || duration > current.getDuration()) {
65 final DurationWithTime newObj = new DurationWithTime(duration, System.currentTimeMillis());
66 while (!LONGEST_UPDATER.weakCompareAndSet(this, current, newObj)) {
68 if (current != null && duration <= current.getDuration()) {
76 public final long getTotalDurations() {
81 public final double getAverageDuration() {
82 final long myCount = count;
83 return myCount == 0 ? 0 : UnsignedLong.fromLongBits(sum).doubleValue() / myCount;
87 public final synchronized void reset() {
88 // Synchronized is just to make sure we do not have concurrent resets :)
96 protected final DurationWithTime getLongest() {
101 protected final DurationWithTime getShortest() {