1 //******************************************************************************
2 //
3 // File: SharedCharacter.java
4 // Package: edu.rit.pj.reduction
5 // Unit: Class edu.rit.pj.reduction.SharedCharacter
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.AtomicInteger;
44
45 /**
46 * Class SharedCharacter provides a reduction variable for a value of type
47 * <code>char</code>.
48 * <P>
49 * Class SharedCharacter is multiple thread safe. The methods use lock-free
50 * atomic compare-and-set.
51 * <P>
52 * <I>Note:</I> Class SharedCharacter is implemented using class
53 * java.util.concurrent.atomic.AtomicInteger. The character value is stored as
54 * an <code>int</code> whose values are restricted to the range of type
55 * <code>char</code>.
56 *
57 * @author Alan Kaminsky
58 * @version 07-Jun-2007
59 */
60 public class SharedCharacter
61 extends Number {
62
63 @Serial
64 private static final long serialVersionUID = 1L;
65
66 // Hidden data members.
67 private AtomicInteger myValue;
68
69 // Exported constructors.
70 /**
71 * Construct a new character reduction variable with the initial value 0.
72 */
73 public SharedCharacter() {
74 myValue = new AtomicInteger();
75 }
76
77 /**
78 * Construct a new character reduction variable with the given initial
79 * value.
80 *
81 * @param initialValue Initial value.
82 */
83 public SharedCharacter(char initialValue) {
84 myValue = new AtomicInteger(initialValue);
85 }
86
87 // Exported operations.
88 /**
89 * Returns this reduction variable's current value.
90 *
91 * @return Current value.
92 */
93 public char get() {
94 return (char) myValue.get();
95 }
96
97 /**
98 * Set this reduction variable to the given value.
99 *
100 * @param value New value.
101 */
102 public void set(char value) {
103 myValue.set(value);
104 }
105
106 /**
107 * Set this reduction variable to the given value and return the previous
108 * value.
109 *
110 * @param value New value.
111 * @return Previous value.
112 */
113 public char getAndSet(char value) {
114 return (char) myValue.getAndSet(value);
115 }
116
117 /**
118 * Atomically set this reduction variable to the given updated value if the
119 * current value equals the expected value.
120 *
121 * @param expect Expected value.
122 * @param update Updated value.
123 * @return True if the update happened, false otherwise.
124 */
125 public boolean compareAndSet(char expect,
126 char update) {
127 return myValue.compareAndSet(expect, update);
128 }
129
130 /**
131 * Atomically set this reduction variable to the given updated value if the
132 * current value equals the expected value. May fail spuriously.
133 *
134 * @param expect Expected value.
135 * @param update Updated value.
136 * @return True if the update happened, false otherwise.
137 */
138 @SuppressWarnings("deprecation")
139 public boolean weakCompareAndSet(char expect,
140 char update) {
141 return myValue.weakCompareAndSet(expect, update);
142 }
143
144 /**
145 * Add one to this reduction variable and return the previous value.
146 *
147 * @return Previous value.
148 */
149 public char getAndIncrement() {
150 for (;;) {
151 char oldvalue = (char) myValue.get();
152 char newvalue = (char) (oldvalue + 1);
153 if (myValue.compareAndSet(oldvalue, newvalue)) {
154 return oldvalue;
155 }
156 }
157 }
158
159 /**
160 * Subtract one from this reduction variable and return the previous value.
161 *
162 * @return Previous value.
163 */
164 public char getAndDecrement() {
165 for (;;) {
166 char oldvalue = (char) myValue.get();
167 char newvalue = (char) (oldvalue - 1);
168 if (myValue.compareAndSet(oldvalue, newvalue)) {
169 return oldvalue;
170 }
171 }
172 }
173
174 /**
175 * Add the given value to this reduction variable and return the previous
176 * value.
177 *
178 * @param value Value to add.
179 * @return Previous value.
180 */
181 public char getAndAdd(char value) {
182 for (;;) {
183 char oldvalue = (char) myValue.get();
184 char newvalue = (char) (oldvalue + value);
185 if (myValue.compareAndSet(oldvalue, newvalue)) {
186 return oldvalue;
187 }
188 }
189 }
190
191 /**
192 * Add one to this reduction variable and return the new value.
193 *
194 * @return New value.
195 */
196 public char incrementAndGet() {
197 for (;;) {
198 char oldvalue = (char) myValue.get();
199 char newvalue = (char) (oldvalue + 1);
200 if (myValue.compareAndSet(oldvalue, newvalue)) {
201 return newvalue;
202 }
203 }
204 }
205
206 /**
207 * Subtract one from this reduction variable and return the new value.
208 *
209 * @return New value.
210 */
211 public char decrementAndGet() {
212 for (;;) {
213 char oldvalue = (char) myValue.get();
214 char newvalue = (char) (oldvalue - 1);
215 if (myValue.compareAndSet(oldvalue, newvalue)) {
216 return newvalue;
217 }
218 }
219 }
220
221 /**
222 * Add the given value to this reduction variable and return the new value.
223 *
224 * @param value Value to add.
225 * @return New value.
226 */
227 public char addAndGet(char value) {
228 for (;;) {
229 char oldvalue = (char) myValue.get();
230 char newvalue = (char) (oldvalue + value);
231 if (myValue.compareAndSet(oldvalue, newvalue)) {
232 return newvalue;
233 }
234 }
235 }
236
237 /**
238 * Combine this reduction variable with the given value using the given
239 * operation. The result is stored back into this reduction variable and is
240 * returned.
241 *
242 * @param value Value.
243 * @param op Binary operation.
244 * @return (This variable) <I>op</I> (<code>value</code>).
245 */
246 public char reduce(char value,
247 CharacterOp op) {
248 for (;;) {
249 char oldvalue = (char) myValue.get();
250 char newvalue = op.op(oldvalue, value);
251 if (myValue.compareAndSet(oldvalue, newvalue)) {
252 return newvalue;
253 }
254 }
255 }
256
257 /**
258 * Returns a string version of this reduction variable.
259 *
260 * @return String version.
261 */
262 public String toString() {
263 return Character.toString(get());
264 }
265
266 /**
267 * Returns this reduction variable's current value converted to type
268 * <code>int</code>.
269 *
270 * @return Current value.
271 */
272 public int intValue() {
273 return get();
274 }
275
276 /**
277 * Returns this reduction variable's current value converted to type
278 * <code>long</code>.
279 *
280 * @return Current value.
281 */
282 public long longValue() {
283 return get();
284 }
285
286 /**
287 * Returns this reduction variable's current value converted to type
288 * <code>float</code>.
289 *
290 * @return Current value.
291 */
292 public float floatValue() {
293 return get();
294 }
295
296 /**
297 * Returns this reduction variable's current value converted to type
298 * <code>double</code>.
299 *
300 * @return Current value.
301 */
302 public double doubleValue() {
303 return get();
304 }
305
306 }