11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Written by Doug Lea and Martin Buchholz with assistance from
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * members of JCP JSR-166 Expert Group and released to the public
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * domain, as explained at
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://creativecommons.org/publicdomain/zero/1.0/
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Source:
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck-jsr166e/AtomicDoubleArrayTest.java?revision=1.13
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * (Modified to adapt to guava coding conventions)
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent;
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
160888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.*;
170888a09821a98ac0680fad765217302858e70fa4Paul Duffin
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays;
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit test for {@link AtomicDoubleArray}.
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class AtomicDoubleArrayTest extends JSR166TestCase {
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final double[] VALUES = {
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Double.NEGATIVE_INFINITY,
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    -Double.MAX_VALUE,
280888a09821a98ac0680fad765217302858e70fa4Paul Duffin    (double) Long.MIN_VALUE,
290888a09821a98ac0680fad765217302858e70fa4Paul Duffin    (double) Integer.MIN_VALUE,
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    -Math.PI,
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    -1.0,
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    -Double.MIN_VALUE,
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    -0.0,
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    +0.0,
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Double.MIN_VALUE,
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    1.0,
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Math.PI,
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin    (double) Integer.MAX_VALUE,
390888a09821a98ac0680fad765217302858e70fa4Paul Duffin    (double) Long.MAX_VALUE,
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Double.MAX_VALUE,
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Double.POSITIVE_INFINITY,
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Double.NaN,
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Float.MAX_VALUE,
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  };
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** The notion of equality used by AtomicDoubleArray */
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static boolean bitEquals(double x, double y) {
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y);
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static void assertBitEquals(double x, double y) {
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(Double.doubleToRawLongBits(x),
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                 Double.doubleToRawLongBits(y));
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constructor creates array of given size with all elements zero
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstructor() {
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < SIZE; i++) {
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(0.0, aa.get(i));
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constructor with null array throws NPE
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstructor2NPE() {
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      double[] a = null;
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicDoubleArray aa = new AtomicDoubleArray(a);
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      shouldThrow();
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NullPointerException success) {}
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constructor with array is of same size and has all elements
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstructor2() {
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(VALUES);
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(VALUES.length, aa.length());
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < VALUES.length; i++) {
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(VALUES[i], aa.get(i));
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constructor with empty array has size 0 and contains no elements
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstructorEmptyArray() {
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(new double[0]);
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, aa.length());
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aa.get(0);
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      shouldThrow();
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IndexOutOfBoundsException success) {}
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constructor with length zero has size 0 and contains no elements
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstructorZeroLength() {
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(0);
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, aa.length());
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aa.get(0);
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      shouldThrow();
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IndexOutOfBoundsException success) {}
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * get and set for out of bound indices throw IndexOutOfBoundsException
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testIndexing() {
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int index : new int[] { -1, SIZE }) {
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.get(index);
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.set(index, 1.0);
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.lazySet(index, 1.0);
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.compareAndSet(index, 1.0, 2.0);
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.weakCompareAndSet(index, 1.0, 2.0);
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.getAndAdd(index, 1.0);
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aa.addAndGet(index, 1.0);
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        shouldThrow();
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (IndexOutOfBoundsException success) {}
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * get returns the last value set at index
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testGetSet() {
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length);
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < VALUES.length; i++) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(0.0, aa.get(i));
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aa.set(i, VALUES[i]);
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(VALUES[i], aa.get(i));
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aa.set(i, -3.0);
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(-3.0, aa.get(i));
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * get returns the last value lazySet at index by same thread
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testGetLazySet() {
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length);
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < VALUES.length; i++) {
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(0.0, aa.get(i));
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aa.lazySet(i, VALUES[i]);
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(VALUES[i], aa.get(i));
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aa.lazySet(i, -3.0);
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(-3.0, aa.get(i));
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * compareAndSet succeeds in changing value if equal to expected else fails
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testCompareAndSet() {
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i : new int[] { 0, SIZE - 1}) {
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      double prev = 0.0;
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      double unused = Math.E + Math.PI;
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (double x : VALUES) {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(prev, aa.get(i));
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertFalse(aa.compareAndSet(i, unused, x));
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(prev, aa.get(i));
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertTrue(aa.compareAndSet(i, prev, x));
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(x, aa.get(i));
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        prev = x;
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * compareAndSet in one thread enables another waiting for value
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * to succeed
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void testCompareAndSetInMultipleThreads() throws InterruptedException {
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicDoubleArray a = new AtomicDoubleArray(1);
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    a.set(0, 1.0);
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Thread t = newStartedThread(new CheckedRunnable() {
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public void realRun() {
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          while (!a.compareAndSet(0, 2.0, 3.0)) {
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            Thread.yield();
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }});
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(a.compareAndSet(0, 1.0, 2.0));
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    awaitTermination(t);
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertBitEquals(3.0, a.get(0));
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * repeated weakCompareAndSet succeeds in changing value when equal
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * to expected
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testWeakCompareAndSet() {
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i : new int[] { 0, SIZE - 1}) {
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      double prev = 0.0;
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      double unused = Math.E + Math.PI;
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (double x : VALUES) {
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(prev, aa.get(i));
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertFalse(aa.weakCompareAndSet(i, unused, x));
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(prev, aa.get(i));
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        while (!aa.weakCompareAndSet(i, prev, x)) {
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ;
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(x, aa.get(i));
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        prev = x;
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * getAndSet returns previous value and sets to given value at given index
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testGetAndSet() {
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i : new int[] { 0, SIZE - 1}) {
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      double prev = 0.0;
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (double x : VALUES) {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertBitEquals(prev, aa.getAndSet(i, x));
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        prev = x;
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * getAndAdd returns previous value and adds given value
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testGetAndAdd() {
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i : new int[] { 0, SIZE - 1}) {
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (double x : VALUES) {
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (double y : VALUES) {
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          aa.set(i, x);
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          double z = aa.getAndAdd(i, y);
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          assertBitEquals(x, z);
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          assertBitEquals(x + y, aa.get(i));
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * addAndGet adds given value to current, and returns current value
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testAddAndGet() {
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i : new int[] { 0, SIZE - 1}) {
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (double x : VALUES) {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (double y : VALUES) {
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          aa.set(i, x);
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          double z = aa.addAndGet(i, y);
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          assertBitEquals(x + y, z);
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          assertBitEquals(x + y, aa.get(i));
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final long COUNTDOWN = 100000;
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  class Counter extends CheckedRunnable {
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicDoubleArray aa;
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long counts;
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Counter(AtomicDoubleArray a) { aa = a; }
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void realRun() {
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (;;) {
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        boolean done = true;
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int i = 0; i < aa.length(); i++) {
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          double v = aa.get(i);
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          assertTrue(v >= 0);
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (v != 0) {
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            done = false;
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (aa.compareAndSet(i, v, v - 1.0)) {
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ++counts;
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (done) {
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          break;
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Multiple threads using same array of counters successfully
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * update a number of times equal to total count
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void testCountingInMultipleThreads() throws InterruptedException {
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < SIZE; i++) {
3200888a09821a98ac0680fad765217302858e70fa4Paul Duffin      aa.set(i, (double) COUNTDOWN);
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Counter c1 = new Counter(aa);
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Counter c2 = new Counter(aa);
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Thread t1 = newStartedThread(c1);
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Thread t2 = newStartedThread(c2);
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    awaitTermination(t1);
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    awaitTermination(t2);
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(c1.counts + c2.counts, SIZE * COUNTDOWN);
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * a deserialized serialized array holds same values
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testSerialization() throws Exception {
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray x = new AtomicDoubleArray(SIZE);
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < SIZE; i++) {
3370888a09821a98ac0680fad765217302858e70fa4Paul Duffin      x.set(i, (double) -i);
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray y = serialClone(x);
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(x != y);
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(x.length(), y.length());
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < SIZE; i++) {
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(x.get(i), y.get(i));
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray a = new AtomicDoubleArray(VALUES);
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray b = serialClone(a);
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(a.equals(b));
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(b.equals(a));
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(a.length(), b.length());
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < VALUES.length; i++) {
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(a.get(i), b.get(i));
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * toString returns current value
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testToString() {
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(VALUES);
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(Arrays.toString(VALUES), aa.toString());
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("[]", new AtomicDoubleArray(0).toString());
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("[]", new AtomicDoubleArray(new double[0]).toString());
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * compareAndSet treats +0.0 and -0.0 as distinct values
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDistinctZeros() {
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicDoubleArray aa = new AtomicDoubleArray(SIZE);
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i : new int[] { 0, SIZE - 1}) {
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertFalse(aa.compareAndSet(i, -0.0, 7.0));
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertFalse(aa.weakCompareAndSet(i, -0.0, 7.0));
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(+0.0, aa.get(i));
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertTrue(aa.compareAndSet(i, +0.0, -0.0));
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(-0.0, aa.get(i));
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertFalse(aa.compareAndSet(i, +0.0, 7.0));
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertFalse(aa.weakCompareAndSet(i, +0.0, 7.0));
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertBitEquals(-0.0, aa.get(i));
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
383