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