2222import io .opentelemetry .sdk .resources .Resource ;
2323import java .util .Collection ;
2424import java .util .List ;
25- import java .util .Objects ;
26- import java .util .concurrent .atomic . AtomicReference ;
25+ import java .util .concurrent . locks . Lock ;
26+ import java .util .concurrent .locks . ReentrantLock ;
2727import java .util .function .Supplier ;
2828import javax .annotation .Nullable ;
2929import javax .annotation .concurrent .ThreadSafe ;
@@ -114,8 +114,7 @@ public MetricData toMetricData(
114114 }
115115
116116 static final class Handle extends AggregatorHandle <DoublePointData , DoubleExemplarData > {
117- @ Nullable private static final Double DEFAULT_VALUE = null ;
118- private final AtomicReference <Double > current = new AtomicReference <>(DEFAULT_VALUE );
117+ private final AtomicDouble current = new AtomicDouble ();
119118
120119 // Only used when memoryMode is REUSABLE_DATA
121120 @ Nullable private final MutableDoublePointData reusablePoint ;
@@ -136,20 +135,50 @@ protected DoublePointData doAggregateThenMaybeReset(
136135 Attributes attributes ,
137136 List <DoubleExemplarData > exemplars ,
138137 boolean reset ) {
139- Double value = reset ? this .current .getAndSet (DEFAULT_VALUE ) : this .current .get ();
140- if (reusablePoint != null ) {
141- reusablePoint .set (
142- startEpochNanos , epochNanos , attributes , Objects .requireNonNull (value ), exemplars );
143- return reusablePoint ;
144- } else {
138+ double currentDouble = current .getAndReset ();
139+ if (reusablePoint == null ) {
145140 return ImmutableDoublePointData .create (
146- startEpochNanos , epochNanos , attributes , Objects . requireNonNull ( value ) , exemplars );
141+ startEpochNanos , epochNanos , attributes , currentDouble , exemplars );
147142 }
143+ reusablePoint .set (startEpochNanos , epochNanos , attributes , currentDouble , exemplars );
144+ return reusablePoint ;
148145 }
149146
150147 @ Override
151148 protected void doRecordDouble (double value ) {
152149 current .set (value );
153150 }
154151 }
152+
153+ private static final class AtomicDouble {
154+ private final Lock lock = new ReentrantLock ();
155+ private long current = 0 ;
156+ private boolean set = false ;
157+
158+ public void set (double value ) {
159+ long longValue = Double .doubleToLongBits (value );
160+ lock .lock ();
161+ try {
162+ current = longValue ;
163+ set = true ;
164+ } finally {
165+ lock .unlock ();
166+ }
167+ }
168+
169+ public double getAndReset () {
170+ long currentLocal ;
171+ lock .lock ();
172+ try {
173+ if (!set ) {
174+ return 0 ;
175+ }
176+ currentLocal = current ;
177+ set = false ;
178+ } finally {
179+ lock .unlock ();
180+ }
181+ return Double .longBitsToDouble (currentLocal );
182+ }
183+ }
155184}
0 commit comments