View Javadoc
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 }