AtomicMarkableReference.java revision adc854b798c1cfe3bfd4c27d68d5cee38ca617da
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Written by Doug Lea with assistance from members of JCP JSR-166
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expert Group and released to the public domain, as explained at
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://creativecommons.org/licenses/publicdomain
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.concurrent.atomic;
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * An <tt>AtomicMarkableReference</tt> maintains an object reference
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * along with a mark bit, that can be updated atomically.
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> Implementation note. This implementation maintains markable
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * references by creating internal objects representing "boxed"
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * [reference, boolean] pairs.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @since 1.5
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Doug Lea
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param <V> The type of object referred to by this reference
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class AtomicMarkableReference<V>  {
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static class ReferenceBooleanPair<T> {
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private final T reference;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private final boolean bit;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ReferenceBooleanPair(T r, boolean i) {
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            reference = r; bit = i;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final AtomicReference<ReferenceBooleanPair<V>>  atomicRef;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new <tt>AtomicMarkableReference</tt> with the given
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * initial values.
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param initialRef the initial reference
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param initialMark the initial mark
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public AtomicMarkableReference(V initialRef, boolean initialMark) {
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark));
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the current value of the reference.
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the current value of the reference
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public V getReference() {
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return atomicRef.get().reference;
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the current value of the mark.
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the current value of the mark
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isMarked() {
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return atomicRef.get().bit;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the current values of both the reference and the mark.
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Typical usage is <tt>boolean[1] holder; ref = v.get(holder); </tt>.
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param markHolder an array of size of at least one. On return,
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <tt>markholder[0]</tt> will hold the value of the mark.
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the current value of the reference
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public V get(boolean[] markHolder) {
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ReferenceBooleanPair<V> p = atomicRef.get();
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        markHolder[0] = p.bit;
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return p.reference;
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Atomically sets the value of both the reference and mark
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to the given update values if the
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * current reference is <tt>==</tt> to the expected reference
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and the current mark is equal to the expected mark.  Any given
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * invocation of this operation may fail (return
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <tt>false</tt>) spuriously, but repeated invocation when
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the current value holds the expected value and no other thread
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is also attempting to set the value will eventually succeed.
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expectedReference the expected value of the reference
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newReference the new value for the reference
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expectedMark the expected value of the mark
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newMark the new value for the mark
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if successful
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean weakCompareAndSet(V       expectedReference,
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                     V       newReference,
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                     boolean expectedMark,
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                     boolean newMark) {
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ReferenceBooleanPair current = atomicRef.get();
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return  expectedReference == current.reference &&
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            expectedMark == current.bit &&
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ((newReference == current.reference && newMark == current.bit) ||
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             atomicRef.weakCompareAndSet(current,
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                     new ReferenceBooleanPair<V>(newReference,
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                              newMark)));
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Atomically sets the value of both the reference and mark
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to the given update values if the
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * current reference is <tt>==</tt> to the expected reference
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and the current mark is equal to the expected mark.
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expectedReference the expected value of the reference
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newReference the new value for the reference
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expectedMark the expected value of the mark
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newMark the new value for the mark
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if successful
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean compareAndSet(V       expectedReference,
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                 V       newReference,
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                 boolean expectedMark,
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                 boolean newMark) {
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ReferenceBooleanPair current = atomicRef.get();
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return  expectedReference == current.reference &&
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            expectedMark == current.bit &&
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ((newReference == current.reference && newMark == current.bit) ||
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             atomicRef.compareAndSet(current,
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                     new ReferenceBooleanPair<V>(newReference,
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                              newMark)));
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Unconditionally sets the value of both the reference and mark.
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newReference the new value for the reference
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newMark the new value for the mark
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void set(V newReference, boolean newMark) {
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ReferenceBooleanPair current = atomicRef.get();
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (newReference != current.reference || newMark != current.bit)
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark));
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Atomically sets the value of the mark to the given update value
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if the current reference is <tt>==</tt> to the expected
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * reference.  Any given invocation of this operation may fail
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * (return <tt>false</tt>) spuriously, but repeated invocation
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * when the current value holds the expected value and no other
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * thread is also attempting to set the value will eventually
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * succeed.
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expectedReference the expected value of the reference
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newMark the new value for the mark
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if successful
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean attemptMark(V expectedReference, boolean newMark) {
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ReferenceBooleanPair current = atomicRef.get();
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return  expectedReference == current.reference &&
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            (newMark == current.bit ||
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             atomicRef.compareAndSet
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             (current, new ReferenceBooleanPair<V>(expectedReference,
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                newMark)));
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
164