1. /*
  2. * @(#)AtomicReferenceArray.java 1.6 04/01/24
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.concurrent.atomic;
  8. import sun.misc.Unsafe;
  9. import java.util.*;
  10. /**
  11. * An array of object references in which elements may be updated
  12. * atomically. See the {@link java.util.concurrent.atomic} package
  13. * specification for description of the properties of atomic
  14. * variables.
  15. * @since 1.5
  16. * @author Doug Lea
  17. * @param <E> The base class of elements held in this array
  18. */
  19. public class AtomicReferenceArray<E> implements java.io.Serializable {
  20. private static final long serialVersionUID = -6209656149925076980L;
  21. private static final Unsafe unsafe = Unsafe.getUnsafe();
  22. private static final int base = unsafe.arrayBaseOffset(Object[].class);
  23. private static final int scale = unsafe.arrayIndexScale(Object[].class);
  24. private final Object[] array;
  25. private long rawIndex(int i) {
  26. if (i < 0 || i >= array.length)
  27. throw new IndexOutOfBoundsException("index " + i);
  28. return base + i * scale;
  29. }
  30. /**
  31. * Create a new AtomicReferenceArray of given length.
  32. * @param length the length of the array
  33. */
  34. public AtomicReferenceArray(int length) {
  35. array = new Object[length];
  36. // must perform at least one volatile write to conform to JMM
  37. if (length > 0)
  38. unsafe.putObjectVolatile(array, rawIndex(0), null);
  39. }
  40. /**
  41. * Create a new AtomicReferenceArray with the same length as, and
  42. * all elements copied from, the given array.
  43. *
  44. * @param array the array to copy elements from
  45. * @throws NullPointerException if array is null
  46. */
  47. public AtomicReferenceArray(E[] array) {
  48. if (array == null)
  49. throw new NullPointerException();
  50. int length = array.length;
  51. this.array = new Object[length];
  52. if (length > 0) {
  53. int last = length-1;
  54. for (int i = 0; i < last; ++i)
  55. this.array[i] = array[i];
  56. // Do the last write as volatile
  57. E e = array[last];
  58. unsafe.putObjectVolatile(this.array, rawIndex(last), e);
  59. }
  60. }
  61. /**
  62. * Returns the length of the array.
  63. *
  64. * @return the length of the array
  65. */
  66. public final int length() {
  67. return array.length;
  68. }
  69. /**
  70. * Get the current value at position <tt>i</tt>.
  71. *
  72. * @param i the index
  73. * @return the current value
  74. */
  75. public final E get(int i) {
  76. return (E) unsafe.getObjectVolatile(array, rawIndex(i));
  77. }
  78. /**
  79. * Set the element at position <tt>i</tt> to the given value.
  80. *
  81. * @param i the index
  82. * @param newValue the new value
  83. */
  84. public final void set(int i, E newValue) {
  85. unsafe.putObjectVolatile(array, rawIndex(i), newValue);
  86. }
  87. /**
  88. * Set the element at position <tt>i</tt> to the given value and return the
  89. * old value.
  90. *
  91. * @param i the index
  92. * @param newValue the new value
  93. * @return the previous value
  94. */
  95. public final E getAndSet(int i, E newValue) {
  96. while (true) {
  97. E current = get(i);
  98. if (compareAndSet(i, current, newValue))
  99. return current;
  100. }
  101. }
  102. /**
  103. * Atomically set the value to the given updated value
  104. * if the current value <tt>==</tt> the expected value.
  105. * @param i the index
  106. * @param expect the expected value
  107. * @param update the new value
  108. * @return true if successful. False return indicates that
  109. * the actual value was not equal to the expected value.
  110. */
  111. public final boolean compareAndSet(int i, E expect, E update) {
  112. return unsafe.compareAndSwapObject(array, rawIndex(i),
  113. expect, update);
  114. }
  115. /**
  116. * Atomically set the value to the given updated value
  117. * if the current value <tt>==</tt> the expected value.
  118. * May fail spuriously.
  119. * @param i the index
  120. * @param expect the expected value
  121. * @param update the new value
  122. * @return true if successful.
  123. */
  124. public final boolean weakCompareAndSet(int i, E expect, E update) {
  125. return compareAndSet(i, expect, update);
  126. }
  127. /**
  128. * Returns the String representation of the current values of array.
  129. * @return the String representation of the current values of array.
  130. */
  131. public String toString() {
  132. if (array.length > 0) // force volatile read
  133. get(0);
  134. return Arrays.toString(array);
  135. }
  136. }