//******************************************************************************
//
// File:    SharedLongMatrix.java
// Package: edu.rit.pj.reduction
// Unit:    Class edu.rit.pj.reduction.SharedLongMatrix
//
// This Java source file is copyright (C) 2010 by Alan Kaminsky. All rights
// reserved. For further information, contact the author, Alan Kaminsky, at
// ark@cs.rit.edu.
//
// This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
// software; you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// PJ is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// A copy of the GNU General Public License is provided in the file gpl.txt. You
// may also obtain a copy of the GNU General Public License on the World Wide
// Web at http://www.gnu.org/licenses/gpl.html.
//
//******************************************************************************

package edu.rit.pj.reduction;

import java.util.concurrent.atomic.AtomicLongArray;

/**
 * Class SharedLongMatrix provides a matrix reduction variable with elements
 * of type long.
 * 

* Class SharedLongMatrix is multiple thread safe. The methods use lock-free * atomic compare-and-set. *

* Note: Class SharedLongMatrix is implemented using class * java.util.concurrent.atomic.AtomicLongArray. * * @author Alan Kaminsky * @version 12-Feb-2010 */ public class SharedLongMatrix { // Hidden data members. private AtomicLongArray[] myMatrix; // Exported constructors. /** * Construct a new long matrix reduction variable with the given number of * rows and columns. Each matrix element is initially 0. * * @param rows Number of rows. * @param cols Number of columns. * * @exception NegativeArraySizeException * (unchecked exception) Thrown if rows < 0 or cols * < 0. */ public SharedLongMatrix (int rows, int cols) { myMatrix = new AtomicLongArray [rows]; for (int r = 0; r < rows; ++ r) { myMatrix[r] = new AtomicLongArray (cols); } } /** * Construct a new long matrix reduction variable whose elements are * copied from the given matrix. It is assumed that all rows of the * matrix have the same number of columns. * * @param matrix Matrix to copy. * * @exception NullPointerException * (unchecked exception) Thrown if matrix is null or any row of * matrix is null. */ public SharedLongMatrix (long[][] matrix) { myMatrix = new AtomicLongArray [matrix.length]; for (int r = 0; r < matrix.length; ++ r) { myMatrix[r] = new AtomicLongArray (matrix[r]); } } // Exported operations. /** * Returns the number of rows in this matrix reduction variable. * * @return Rows. */ public int rows() { return myMatrix.length; } /** * Returns the number of columns in this matrix reduction variable. * * @return Columns. */ public int cols() { return myMatrix[0].length(); } /** * Returns this matrix reduction variable's current value at the given row * and column. * * @param r Row index. * @param c Column index. * * @return Current value. */ public long get (int r, int c) { return myMatrix[r].get (c); } /** * Set this matrix reduction variable at the given row and column to the * given value. * * @param r Row index. * @param c Column index. * @param value New value. */ public void set (int r, int c, long value) { myMatrix[r].set (c, value); } /** * Set this matrix reduction variable at the given row and column to the * given value and return the previous value. * * @param r Row index. * @param c Column index. * @param value New value. * * @return Previous value. */ public long getAndSet (int r, int c, long value) { return myMatrix[r].getAndSet (c, value); } /** * Atomically set this matrix reduction variable at the given row and column * to the given updated value if the current value equals the expected * value. * * @param r Row index. * @param c Column index. * @param expect Expected value. * @param update Updated value. * * @return True if the update happened, false otherwise. */ public boolean compareAndSet (int r, int c, long expect, long update) { return myMatrix[r].compareAndSet (c, expect, update); } /** * Atomically set this matrix reduction variable at the given row and column * to the given updated value if the current value equals the expected * value. May fail spuriously. * * @param r Row index. * @param c Column index. * @param expect Expected value. * @param update Updated value. * * @return True if the update happened, false otherwise. */ public boolean weakCompareAndSet (int r, int c, long expect, long update) { return myMatrix[r].weakCompareAndSet (c, expect, update); } /** * Add one to this matrix reduction variable at the given row and column and * return the previous value. * * @param r Row index. * @param c Column index. * * @return Previous value. */ public long getAndIncrement (int r, int c) { return myMatrix[r].getAndIncrement (c); } /** * Subtract one from this matrix reduction variable at the given row and * column and return the previous value. * * @param r Row index. * @param c Column index. * * @return Previous value. */ public long getAndDecrement (int r, int c) { return myMatrix[r].getAndDecrement (c); } /** * Add the given value to this matrix reduction variable at the given row * and column and return the previous value. * * @param r Row index. * @param c Column index. * @param value Value to add. * * @return Previous value. */ public long getAndAdd (int r, int c, long value) { return myMatrix[r].getAndAdd (c, value); } /** * Add one to this matrix reduction variable at the given row and column and * return the new value. * * @param r Row index. * @param c Column index. * * @return New value. */ public long incrementAndGet (int r, int c) { return myMatrix[r].incrementAndGet (c); } /** * Subtract one from this matrix reduction variable at the given row and * column and return the new value. * * @param r Row index. * @param c Column index. * * @return New value. */ public long decrementAndGet (int r, int c) { return myMatrix[r].decrementAndGet (c); } /** * Add the given value to this matrix reduction variable at the given row * and column and return the new value. * * @param r Row index. * @param c Column index. * @param value Value to add. * * @return New value. */ public long addAndGet (int r, int c, long value) { return myMatrix[r].addAndGet (c, value); } /** * Combine this matrix reduction variable at the given row and column with * the given value using the given operation. (This matrix [r,c]) * is set to (this matrix [r,c]) op (value), then * (this matrix [r,c]) is returned. * * @param r Row index. * @param c Column index. * @param value Value. * @param op Binary operation. * * @return (This matrix [r,c]) op (value). */ public long reduce (int r, int c, long value, LongOp op) { AtomicLongArray myMatrix_r = myMatrix[r]; for (;;) { long oldvalue = myMatrix_r.get (c); long newvalue = op.op (oldvalue, value); if (myMatrix_r.compareAndSet (c, oldvalue, newvalue)) { return newvalue; } } } /** * Combine this matrix reduction variable with the given matrix using the * given operation. For every row r and column c in this * matrix, (this matrix [r,c]) is set to (this matrix * [r,c]) op (src[r,c]). *

* The reduce() method is multiple thread safe on a per-element * basis. Each individual matrix element is updated atomically, but the * matrix as a whole is not updated atomically. * * @param src Source matrix. * @param op Binary operation. * * @exception NullPointerException * (unchecked exception) Thrown if src is null. Thrown if * op is null. * @exception IndexOutOfBoundsException * (unchecked exception) Thrown if any matrix index would be out of * bounds. */ public void reduce (long[][] src, LongOp op) { reduce (0, 0, src, 0, 0, rows(), cols(), op); } /** * Combine a portion of this matrix reduction variable with a portion of the * given matrix using the given operation. For each row index r * from 0 to rowlen-1 inclusive, and for each column index * c from 0 to collen-1 inclusive, (this matrix * [dstrow+r,dstcol+c]) is set to (this matrix * [dstrow+r,dstcol+c]) op * (src[srcrow+r,srccol+c]). *

* The reduce() method is multiple thread safe on a per-element * basis. Each individual matrix element is updated atomically, but the * matrix as a whole is not updated atomically. * * @param dstrow Row index of first element to update in this matrix. * @param dstcol Column index of first element to update in this matrix. * @param src Source matrix. * @param srcrow Row index of first element to update from in the source * matrix. * @param srccol Column index of first element to update from in the * source matrix. * @param rowlen Number of rows to update. * @param collen Number of columns to update. * @param op Binary operation. * * @exception NullPointerException * (unchecked exception) Thrown if src is null. Thrown if * op is null. * @exception IndexOutOfBoundsException * (unchecked exception) Thrown if rowlen < 0. Thrown if * collen < 0. Thrown if any matrix index would be out of * bounds. */ public void reduce (int dstrow, int dstcol, long[][] src, int srcrow, int srccol, int rowlen, int collen, LongOp op) { if (rowlen < 0 || collen < 0 || dstrow < 0 || dstrow + rowlen > rows() || dstcol < 0 || dstcol + collen > cols() || srcrow < 0 || srcrow + rowlen > src.length || srccol < 0 || srccol + collen > src[0].length) { throw new IndexOutOfBoundsException(); } for (int r = 0; r < rowlen; ++ r) { AtomicLongArray myMatrix_r = myMatrix[dstrow + r]; long[] src_r = src[srcrow + r]; for (int c = 0; c < collen; ++ c) { int dstcol_c = dstcol + c; long src_r_c = src_r[srccol + c]; updateLoop: for (;;) { long oldvalue = myMatrix_r.get (dstcol_c); long newvalue = op.op (oldvalue, src_r_c); if (myMatrix_r.compareAndSet (dstcol_c, oldvalue, newvalue)) break updateLoop; } } } } }

Ads help maintain this website.