blob: 19b5bf82a17cb3719af04d4801fec86b9c120810 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 * Expert Group and released to the public domain, as explained at
33 * http://creativecommons.org/licenses/publicdomain
34 */
35
36package java.util.concurrent.atomic;
37
38/**
39 * An {@code AtomicMarkableReference} maintains an object reference
40 * along with a mark bit, that can be updated atomically.
41 * <p>
42 * <p> Implementation note. This implementation maintains markable
43 * references by creating internal objects representing "boxed"
44 * [reference, boolean] pairs.
45 *
46 * @since 1.5
47 * @author Doug Lea
48 * @param <V> The type of object referred to by this reference
49 */
50public class AtomicMarkableReference<V> {
51
52 private static class ReferenceBooleanPair<T> {
53 private final T reference;
54 private final boolean bit;
55 ReferenceBooleanPair(T r, boolean i) {
56 reference = r; bit = i;
57 }
58 }
59
60 private final AtomicReference<ReferenceBooleanPair<V>> atomicRef;
61
62 /**
63 * Creates a new {@code AtomicMarkableReference} with the given
64 * initial values.
65 *
66 * @param initialRef the initial reference
67 * @param initialMark the initial mark
68 */
69 public AtomicMarkableReference(V initialRef, boolean initialMark) {
70 atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark));
71 }
72
73 /**
74 * Returns the current value of the reference.
75 *
76 * @return the current value of the reference
77 */
78 public V getReference() {
79 return atomicRef.get().reference;
80 }
81
82 /**
83 * Returns the current value of the mark.
84 *
85 * @return the current value of the mark
86 */
87 public boolean isMarked() {
88 return atomicRef.get().bit;
89 }
90
91 /**
92 * Returns the current values of both the reference and the mark.
93 * Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
94 *
95 * @param markHolder an array of size of at least one. On return,
96 * {@code markholder[0]} will hold the value of the mark.
97 * @return the current value of the reference
98 */
99 public V get(boolean[] markHolder) {
100 ReferenceBooleanPair<V> p = atomicRef.get();
101 markHolder[0] = p.bit;
102 return p.reference;
103 }
104
105 /**
106 * Atomically sets the value of both the reference and mark
107 * to the given update values if the
108 * current reference is {@code ==} to the expected reference
109 * and the current mark is equal to the expected mark.
110 *
111 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
112 * and does not provide ordering guarantees, so is only rarely an
113 * appropriate alternative to {@code compareAndSet}.
114 *
115 * @param expectedReference the expected value of the reference
116 * @param newReference the new value for the reference
117 * @param expectedMark the expected value of the mark
118 * @param newMark the new value for the mark
119 * @return true if successful
120 */
121 public boolean weakCompareAndSet(V expectedReference,
122 V newReference,
123 boolean expectedMark,
124 boolean newMark) {
125 ReferenceBooleanPair<V> current = atomicRef.get();
126 return expectedReference == current.reference &&
127 expectedMark == current.bit &&
128 ((newReference == current.reference && newMark == current.bit) ||
129 atomicRef.weakCompareAndSet(current,
130 new ReferenceBooleanPair<V>(newReference,
131 newMark)));
132 }
133
134 /**
135 * Atomically sets the value of both the reference and mark
136 * to the given update values if the
137 * current reference is {@code ==} to the expected reference
138 * and the current mark is equal to the expected mark.
139 *
140 * @param expectedReference the expected value of the reference
141 * @param newReference the new value for the reference
142 * @param expectedMark the expected value of the mark
143 * @param newMark the new value for the mark
144 * @return true if successful
145 */
146 public boolean compareAndSet(V expectedReference,
147 V newReference,
148 boolean expectedMark,
149 boolean newMark) {
150 ReferenceBooleanPair<V> current = atomicRef.get();
151 return expectedReference == current.reference &&
152 expectedMark == current.bit &&
153 ((newReference == current.reference && newMark == current.bit) ||
154 atomicRef.compareAndSet(current,
155 new ReferenceBooleanPair<V>(newReference,
156 newMark)));
157 }
158
159 /**
160 * Unconditionally sets the value of both the reference and mark.
161 *
162 * @param newReference the new value for the reference
163 * @param newMark the new value for the mark
164 */
165 public void set(V newReference, boolean newMark) {
166 ReferenceBooleanPair<V> current = atomicRef.get();
167 if (newReference != current.reference || newMark != current.bit)
168 atomicRef.set(new ReferenceBooleanPair<V>(newReference, 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 ||
188 atomicRef.compareAndSet
189 (current, new ReferenceBooleanPair<V>(expectedReference,
190 newMark)));
191 }
192}