1 //******************************************************************************
2 //
3 // File: SharedBooleanArray.java
4 // Package: edu.rit.pj.reduction
5 // Unit: Class edu.rit.pj.reduction.SharedBooleanArray
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.util.concurrent.atomic.AtomicIntegerArray;
43
44 /**
45 * Class SharedBooleanArray provides an array reduction variable with elements
46 * of type <code>boolean</code>.
47 * <P>
48 * Class SharedBooleanArray is multiple thread safe. The methods use lock-free
49 * atomic compare-and-set.
50 * <P>
51 * <I>Note:</I> Class SharedBooleanArray is implemented using class
52 * java.util.concurrent.atomic.AtomicIntegerArray. Each Boolean array element is
53 * stored as an <code>int</code> whose values are restricted to the range of type
54 * <code>boolean</code> (0 = <code>false</code>, 1 = <code>true</code>).
55 *
56 * @author Alan Kaminsky
57 * @version 07-Jun-2007
58 */
59 public class SharedBooleanArray {
60
61 // Hidden data members.
62 private AtomicIntegerArray myArray;
63
64 // Exported constructors.
65 /**
66 * Construct a new Boolean array reduction variable with the given length.
67 * Each array element is initially <code>false</code>.
68 *
69 * @param len Length.
70 * @exception NegativeArraySizeException (unchecked exception) Thrown if
71 * <code>len</code> < 0.
72 */
73 public SharedBooleanArray(int len) {
74 myArray = new AtomicIntegerArray(len);
75 }
76
77 /**
78 * Construct a new Boolean array reduction variable whose elements are
79 * copied from the given array.
80 *
81 * @param array Array to copy.
82 * @exception NullPointerException (unchecked exception) Thrown if
83 * <code>array</code> is null.
84 */
85 public SharedBooleanArray(boolean[] array) {
86 int n = array.length;
87 int[] intarray = new int[n];
88 for (int i = 0; i < n; ++i) {
89 intarray[i] = array[i] ? 1 : 0;
90 }
91 myArray = new AtomicIntegerArray(intarray);
92 }
93
94 // Exported operations.
95 /**
96 * Returns this array reduction variable's length.
97 *
98 * @return Length.
99 */
100 public int length() {
101 return myArray.length();
102 }
103
104 /**
105 * Returns this array reduction variable's current value at the given index.
106 *
107 * @param i Index.
108 * @return Current value.
109 */
110 public boolean get(int i) {
111 return myArray.get(i) != 0;
112 }
113
114 /**
115 * Set this array reduction variable at the given index to the given value.
116 *
117 * @param i Index.
118 * @param value New value.
119 */
120 public void set(int i,
121 boolean value) {
122 myArray.set(i, value ? 1 : 0);
123 }
124
125 /**
126 * Set this array reduction variable at the given index to the given value
127 * and return the previous value.
128 *
129 * @param i Index.
130 * @param value New value.
131 * @return Previous value.
132 */
133 public boolean getAndSet(int i,
134 boolean value) {
135 return myArray.getAndSet(i, value ? 1 : 0) != 0;
136 }
137
138 /**
139 * Atomically set this array reduction variable at the given index to the
140 * given updated value if the current value equals the expected value.
141 *
142 * @param i Index.
143 * @param expect Expected value.
144 * @param update Updated value.
145 * @return True if the update happened, false otherwise.
146 */
147 public boolean compareAndSet(int i,
148 boolean expect,
149 boolean update) {
150 return myArray.compareAndSet(i, expect ? 1 : 0, update ? 1 : 0);
151 }
152
153 /**
154 * Atomically set this array reduction variable at the given index to the
155 * given updated value if the current value equals the expected value. May
156 * fail spuriously.
157 *
158 * @param i Index.
159 * @param expect Expected value.
160 * @param update Updated value.
161 * @return True if the update happened, false otherwise.
162 */
163 @SuppressWarnings("deprecation")
164 public boolean weakCompareAndSet(int i,
165 boolean expect,
166 boolean update) {
167 return myArray.weakCompareAndSet(i, expect ? 1 : 0, update ? 1 : 0);
168 }
169
170 /**
171 * Combine this array reduction variable at the given index with the given
172 * value using the given operation. (This array <code>[i]</code>) is set to
173 * (this array <code>[i]</code>) <I>op</I> (<code>value</code>), then (this array
174 * <code>[i]</code>) is returned.
175 *
176 * @param i Index.
177 * @param value Value.
178 * @param op Binary operation.
179 * @return (This array <code>[i]</code>) <I>op</I> (<code>value</code>).
180 */
181 public boolean reduce(int i,
182 boolean value,
183 BooleanOp op) {
184 for (;;) {
185 int oldvalue = myArray.get(i);
186 int newvalue = op.op(oldvalue != 0, value) ? 1 : 0;
187 if (myArray.compareAndSet(i, oldvalue, newvalue)) {
188 return newvalue != 0;
189 }
190 }
191 }
192
193 /**
194 * Combine this array reduction variable with the given array using the
195 * given operation. For each index <code>i</code> from 0 to this array's
196 * length-1, (this array <code>[i]</code>) is set to (this array <code>[i]</code>)
197 * <I>op</I> (<code>src[i]</code>).
198 * <P>
199 * The <code>reduce()</code> method is multiple thread safe <I>on a per-element
200 * basis.</I> Each individual array element is updated atomically, but the
201 * array as a whole is not updated atomically.
202 *
203 * @param src Source array.
204 * @param op Binary operation.
205 * @exception NullPointerException (unchecked exception) Thrown if
206 * <code>src</code> is null. Thrown if
207 * <code>op</code> is null.
208 * @exception IndexOutOfBoundsException (unchecked exception) Thrown if any
209 * array index would be out of bounds.
210 */
211 public void reduce(boolean[] src,
212 BooleanOp op) {
213 reduce(0, src, 0, myArray.length(), op);
214 }
215
216 /**
217 * Combine a portion of this array reduction variable with a portion of the
218 * given array using the given operation. For each index <code>i</code> from 0
219 * to <code>len</code>-1, (this array <code>[dstoff+i]</code>) is set to (this array
220 * <code>[dstoff+i]</code>) <I>op</I> (<code>src[srcoff+i]</code>).
221 * <P>
222 * The <code>reduce()</code> method is multiple thread safe <I>on a per-element
223 * basis.</I> Each individual array element is updated atomically, but the
224 * array as a whole is not updated atomically.
225 *
226 * @param dstoff Index of first element to update in this array.
227 * @param src Source array.
228 * @param srcoff Index of first element to update from in the source array.
229 * @param len Number of array elements to update.
230 * @param op Binary operation.
231 * @exception NullPointerException (unchecked exception) Thrown if
232 * <code>src</code> is null. Thrown if
233 * <code>op</code> is null.
234 * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
235 * <code>len</code> < 0. Thrown if any array index would be out of bounds.
236 */
237 public void reduce(int dstoff,
238 boolean[] src,
239 int srcoff,
240 int len,
241 BooleanOp op) {
242 if (len < 0
243 || dstoff < 0 || dstoff + len > myArray.length()
244 || srcoff < 0 || srcoff + len > src.length) {
245 throw new IndexOutOfBoundsException();
246 }
247 while (len > 0) {
248 updateLoop:
249 for (;;) {
250 int oldvalue = myArray.get(dstoff);
251 int newvalue = op.op(oldvalue != 0, src[srcoff]) ? 1 : 0;
252 if (myArray.compareAndSet(dstoff, oldvalue, newvalue)) {
253 break updateLoop;
254 }
255 }
256 ++dstoff;
257 ++srcoff;
258 --len;
259 }
260 }
261
262 /**
263 * Returns a string version of this array reduction variable.
264 *
265 * @return String version.
266 */
267 public String toString() {
268 return myArray.toString();
269 }
270
271 }