1 //******************************************************************************
2 //
3 // File: SharedLong.java
4 // Package: edu.rit.pj.reduction
5 // Unit: Class edu.rit.pj.reduction.SharedLong
6 //
7 // This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
8 // reserved. For further information, contact the author, Alan Kaminsky, at
9 // ark@cs.rit.edu.
10 //
11 // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12 // software; you can redistribute it and/or modify it under the terms of the GNU
13 // General Public License as published by the Free Software Foundation; either
14 // version 3 of the License, or (at your option) any later version.
15 //
16 // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 //
20 // Linking this library statically or dynamically with other modules is making a
21 // combined work based on this library. Thus, the terms and conditions of the GNU
22 // General Public License cover the whole combination.
23 //
24 // As a special exception, the copyright holders of this library give you
25 // permission to link this library with independent modules to produce an
26 // executable, regardless of the license terms of these independent modules, and
27 // to copy and distribute the resulting executable under terms of your choice,
28 // provided that you also meet, for each linked independent module, the terms
29 // and conditions of the license of that module. An independent module is a module
30 // which is not derived from or based on this library. If you modify this library,
31 // you may extend this exception to your version of the library, but you are not
32 // obligated to do so. If you do not wish to do so, delete this exception
33 // statement from your version.
34 //
35 // A copy of the GNU General Public License is provided in the file gpl.txt. You
36 // may also obtain a copy of the GNU General Public License on the World Wide
37 // Web at http://www.gnu.org/licenses/gpl.html.
38 //
39 //******************************************************************************
40 package edu.rit.pj.reduction;
41
42 import java.io.Serial;
43 import java.util.concurrent.atomic.AtomicLong;
44
45 /**
46 * Class SharedLong provides a reduction variable for a value of type
47 * <code>long</code>.
48 * <P>
49 * Class SharedLong is multiple thread safe. The methods use lock-free atomic
50 * compare-and-set.
51 * <P>
52 * <I>Note:</I> Class SharedLong is implemented using class
53 * java.util.concurrent.atomic.AtomicLong.
54 *
55 * @author Alan Kaminsky
56 * @version 07-Jun-2007
57 */
58 public class SharedLong
59 extends Number {
60
61 @Serial
62 private static final long serialVersionUID = 1L;
63
64 // Hidden data members.
65 private AtomicLong myValue;
66
67 // Exported constructors.
68 /**
69 * Construct a new long reduction variable with the initial value 0.
70 */
71 public SharedLong() {
72 myValue = new AtomicLong();
73 }
74
75 /**
76 * Construct a new long reduction variable with the given initial value.
77 *
78 * @param initialValue Initial value.
79 */
80 public SharedLong(long initialValue) {
81 myValue = new AtomicLong(initialValue);
82 }
83
84 // Exported operations.
85 /**
86 * Returns this reduction variable's current value.
87 *
88 * @return Current value.
89 */
90 public long get() {
91 return myValue.get();
92 }
93
94 /**
95 * Set this reduction variable to the given value.
96 *
97 * @param value New value.
98 */
99 public void set(long value) {
100 myValue.set(value);
101 }
102
103 /**
104 * Set this reduction variable to the given value and return the previous
105 * value.
106 *
107 * @param value New value.
108 * @return Previous value.
109 */
110 public long getAndSet(long value) {
111 return myValue.getAndSet(value);
112 }
113
114 /**
115 * Atomically set this reduction variable to the given updated value if the
116 * current value equals the expected value.
117 *
118 * @param expect Expected value.
119 * @param update Updated value.
120 * @return True if the update happened, false otherwise.
121 */
122 public boolean compareAndSet(long expect,
123 long update) {
124 return myValue.compareAndSet(expect, update);
125 }
126
127 /**
128 * Atomically set this reduction variable to the given updated value if the
129 * current value equals the expected value. May fail spuriously.
130 *
131 * @param expect Expected value.
132 * @param update Updated value.
133 * @return True if the update happened, false otherwise.
134 */
135 @SuppressWarnings("deprecation")
136 public boolean weakCompareAndSet(long expect,
137 long update) {
138 return myValue.weakCompareAndSet(expect, update);
139 }
140
141 /**
142 * Add one to this reduction variable and return the previous value.
143 *
144 * @return Previous value.
145 */
146 public long getAndIncrement() {
147 return myValue.getAndIncrement();
148 }
149
150 /**
151 * Subtract one from this reduction variable and return the previous value.
152 *
153 * @return Previous value.
154 */
155 public long getAndDecrement() {
156 return myValue.getAndDecrement();
157 }
158
159 /**
160 * Add the given value to this reduction variable and return the previous
161 * value.
162 *
163 * @param value Value to add.
164 * @return Previous value.
165 */
166 public long getAndAdd(long value) {
167 return myValue.getAndAdd(value);
168 }
169
170 /**
171 * Add one to this reduction variable and return the new value.
172 *
173 * @return New value.
174 */
175 public long incrementAndGet() {
176 return myValue.incrementAndGet();
177 }
178
179 /**
180 * Subtract one from this reduction variable and return the new value.
181 *
182 * @return New value.
183 */
184 public long decrementAndGet() {
185 return myValue.decrementAndGet();
186 }
187
188 /**
189 * Add the given value to this reduction variable and return the new value.
190 *
191 * @param value Value to add.
192 * @return New value.
193 */
194 public long addAndGet(long value) {
195 return myValue.addAndGet(value);
196 }
197
198 /**
199 * Combine this reduction variable with the given value using the given
200 * operation. The result is stored back into this reduction variable and is
201 * returned.
202 *
203 * @param value Value.
204 * @param op Binary operation.
205 * @return (This variable) <I>op</I> (<code>value</code>).
206 */
207 public long reduce(long value,
208 LongOp op) {
209 for (;;) {
210 long oldvalue = myValue.get();
211 long newvalue = op.op(oldvalue, value);
212 if (myValue.compareAndSet(oldvalue, newvalue)) {
213 return newvalue;
214 }
215 }
216 }
217
218 /**
219 * Returns a string version of this reduction variable.
220 *
221 * @return String version.
222 */
223 public String toString() {
224 return Long.toString(get());
225 }
226
227 /**
228 * Returns this reduction variable's current value converted to type
229 * <code>int</code>.
230 *
231 * @return Current value.
232 */
233 public int intValue() {
234 return (int) get();
235 }
236
237 /**
238 * Returns this reduction variable's current value converted to type
239 * <code>long</code>.
240 *
241 * @return Current value.
242 */
243 public long longValue() {
244 return get();
245 }
246
247 /**
248 * Returns this reduction variable's current value converted to type
249 * <code>float</code>.
250 *
251 * @return Current value.
252 */
253 public float floatValue() {
254 return (float) get();
255 }
256
257 /**
258 * Returns this reduction variable's current value converted to type
259 * <code>double</code>.
260 *
261 * @return Current value.
262 */
263 public double doubleValue() {
264 return (double) get();
265 }
266
267 }