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