001 /*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
003 *
004 * This code is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU General Public License version 2 only, as
006 * published by the Free Software Foundation. Sun designates this
007 * particular file as subject to the "Classpath" exception as provided
008 * by Sun in the LICENSE file that accompanied this code.
009 *
010 * This code is distributed in the hope that it will be useful, but WITHOUT
011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
013 * version 2 for more details (a copy is included in the LICENSE file that
014 * accompanied this code).
015 *
016 * You should have received a copy of the GNU General Public License version
017 * 2 along with this work; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
019 *
020 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
021 * CA 95054 USA or visit www.sun.com if you need additional information or
022 * have any questions.
023 */
024
025 /*
026 * This file is available under and governed by the GNU General Public
027 * License version 2 only, as published by the Free Software Foundation.
028 * However, the following notice accompanied the original version of this
029 * file:
030 *
031 * Written by Doug Lea with assistance from members of JCP JSR-166
032 * Expert Group and released to the public domain, as explained at
033 * http://creativecommons.org/licenses/publicdomain
034 */
035
036 package java.util.concurrent.atomic;
037
038 /**
039 * An {@code AtomicMarkableReference} maintains an object reference
040 * along with a mark bit, that can be updated atomically.
041 * <p>
042 * <p> Implementation note. This implementation maintains markable
043 * references by creating internal objects representing "boxed"
044 * [reference, boolean] pairs.
045 *
046 * @since 1.5
047 * @author Doug Lea
048 * @param <V> The type of object referred to by this reference
049 */
050 public class AtomicMarkableReference<V> {
051
052 private static class ReferenceBooleanPair<T> {
053 private final T reference;
054 private final boolean bit;
055
056 ReferenceBooleanPair(T r, boolean i) {
057 reference = r;
058 bit = i;
059 }
060 }
061
062 private final AtomicReference<ReferenceBooleanPair<V>> atomicRef;
063
064 /**
065 * Creates a new {@code AtomicMarkableReference} with the given
066 * initial values.
067 *
068 * @param initialRef the initial reference
069 * @param initialMark the initial mark
070 */
071 public AtomicMarkableReference(V initialRef, boolean initialMark) {
072 atomicRef = new AtomicReference<ReferenceBooleanPair<V>>(
073 new ReferenceBooleanPair<V>(initialRef, initialMark));
074 }
075
076 /**
077 * Returns the current value of the reference.
078 *
079 * @return the current value of the reference
080 */
081 public V getReference() {
082 return atomicRef.get().reference;
083 }
084
085 /**
086 * Returns the current value of the mark.
087 *
088 * @return the current value of the mark
089 */
090 public boolean isMarked() {
091 return atomicRef.get().bit;
092 }
093
094 /**
095 * Returns the current values of both the reference and the mark.
096 * Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
097 *
098 * @param markHolder an array of size of at least one. On return,
099 * {@code markholder[0]} will hold the value of the mark.
100 * @return the current value of the reference
101 */
102 public V get(boolean[] markHolder) {
103 ReferenceBooleanPair<V> p = atomicRef.get();
104 markHolder[0] = p.bit;
105 return p.reference;
106 }
107
108 /**
109 * Atomically sets the value of both the reference and mark
110 * to the given update values if the
111 * current reference is {@code ==} to the expected reference
112 * and the current mark is equal to the expected mark.
113 *
114 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
115 * and does not provide ordering guarantees, so is only rarely an
116 * appropriate alternative to {@code compareAndSet}.
117 *
118 * @param expectedReference the expected value of the reference
119 * @param newReference the new value for the reference
120 * @param expectedMark the expected value of the mark
121 * @param newMark the new value for the mark
122 * @return true if successful
123 */
124 public boolean weakCompareAndSet(V expectedReference,
125 V newReference, boolean expectedMark, boolean newMark) {
126 ReferenceBooleanPair<V> current = atomicRef.get();
127 return expectedReference == current.reference
128 && expectedMark == current.bit
129 && ((newReference == current.reference && newMark == current.bit) || atomicRef
130 .weakCompareAndSet(current,
131 new ReferenceBooleanPair<V>(
132 newReference, newMark)));
133 }
134
135 /**
136 * Atomically sets the value of both the reference and mark
137 * to the given update values if the
138 * current reference is {@code ==} to the expected reference
139 * and the current mark is equal to the expected mark.
140 *
141 * @param expectedReference the expected value of the reference
142 * @param newReference the new value for the reference
143 * @param expectedMark the expected value of the mark
144 * @param newMark the new value for the mark
145 * @return true if successful
146 */
147 public boolean compareAndSet(V expectedReference, V newReference,
148 boolean expectedMark, boolean newMark) {
149 ReferenceBooleanPair<V> current = atomicRef.get();
150 return expectedReference == current.reference
151 && expectedMark == current.bit
152 && ((newReference == current.reference && newMark == current.bit) || atomicRef
153 .compareAndSet(current,
154 new ReferenceBooleanPair<V>(
155 newReference, newMark)));
156 }
157
158 /**
159 * Unconditionally sets the value of both the reference and mark.
160 *
161 * @param newReference the new value for the reference
162 * @param newMark the new value for the mark
163 */
164 public void set(V newReference, boolean newMark) {
165 ReferenceBooleanPair<V> current = atomicRef.get();
166 if (newReference != current.reference || newMark != current.bit)
167 atomicRef.set(new ReferenceBooleanPair<V>(newReference,
168 newMark));
169 }
170
171 /**
172 * Atomically sets the value of the mark to the given update value
173 * if the current reference is {@code ==} to the expected
174 * reference. Any given invocation of this operation may fail
175 * (return {@code false}) spuriously, but repeated invocation
176 * when the current value holds the expected value and no other
177 * thread is also attempting to set the value will eventually
178 * succeed.
179 *
180 * @param expectedReference the expected value of the reference
181 * @param newMark the new value for the mark
182 * @return true if successful
183 */
184 public boolean attemptMark(V expectedReference, boolean newMark) {
185 ReferenceBooleanPair<V> current = atomicRef.get();
186 return expectedReference == current.reference
187 && (newMark == current.bit || atomicRef.compareAndSet(
188 current, new ReferenceBooleanPair<V>(
189 expectedReference, newMark)));
190 }
191 }
|