00001 /* 00002 * Copyright 2006-2007 Columbia University. 00003 * 00004 * This file is part of MEAPsoft. 00005 * 00006 * MEAPsoft is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License version 2 as 00008 * published by the Free Software Foundation. 00009 * 00010 * MEAPsoft is distributed in the hope that it will be useful, but 00011 * WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with MEAPsoft; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00018 * 02110-1301 USA 00019 * 00020 * See the file "COPYING" for the text of the license. 00021 */ 00022 00023 package com.meapsoft; 00024 00025 import java.util.Stack; 00035 public class RingMatrix { 00036 double[][] M; 00037 int writePos; 00038 long nextFrAddr; 00039 00040 // Keep some extra double[]s around so we don't have to keep 00041 // allocating new ones. For thread safety, use a semaphore to keep 00042 // track of the number of buffers in use. 00043 Stack doubleBuffers = new Stack(); 00044 int dbPoolSize = 4; 00045 00046 public RingMatrix(int rows, int columns) { 00047 M = new double[columns][rows]; 00048 00049 for(int i=0; i<dbPoolSize; i++) 00050 doubleBuffers.push(new double[rows]); 00051 00052 for(int i=0; i<columns; i++) 00053 for(int j=0; j<rows; j++) 00054 M[i][j] = 0; 00055 00056 writePos = 0; 00057 nextFrAddr = 0; 00058 } 00059 00060 // Get a pre-allocated double[] from a pool. If one is not 00061 // available, block until it is. Array is not guaranteed to contain 00062 // anything in particular. 00063 public synchronized double[] checkOutColumn() { 00064 00065 while(doubleBuffers.empty()) { 00066 try { 00067 wait(); 00068 } catch(InterruptedException ie) { 00069 ie.printStackTrace(); 00070 } 00071 } 00072 double[] column = (double[]) doubleBuffers.pop(); 00073 00074 return column; 00075 } 00076 00077 // Check in a previously checked out double buffer. Inserts the db 00078 // into the matrix, but at the same time puts the double[] it's 00079 // replacing back in the pool of double buffers. 00080 public synchronized long checkInColumn(double[] db) { 00081 // remember the replaced array 00082 double[] replaced = M[writePos]; 00083 00084 // do the replacement 00085 M[writePos++] = db; 00086 writePos %= M.length; 00087 long frAddr = nextFrAddr++; 00088 00089 // put the replaced array back in the pool as long as it's not the 00090 // same array 00091 if(replaced != db) { 00092 doubleBuffers.push(replaced); 00093 notify(); 00094 } 00095 00096 return frAddr; 00097 } 00098 00099 // Return a double[] to the pool of double buffers without inserting 00100 // it into the matrix. Does nothing if the array is the wrong 00101 // length. 00102 public synchronized void returnColumn(double[] db) { 00103 if(db.length != M[0].length) 00104 return; 00105 00106 doubleBuffers.push(db); 00107 notify(); 00108 } 00109 00110 // Get a column from the matrix. Throws 00111 // ArrayIndexOutOfBoundsException if the column's address is too 00112 // high (hasn't been written yet) or too low (already overwritten) 00113 public double[] getColumn(long frAddr) { 00114 // if(frAddr < nextFrAddr-M.length) 00115 // throw new ArrayIndexOutOfBoundsException("Frame was already overwritten"); 00116 // if(frAddr >= nextFrAddr) 00117 // throw new ArrayIndexOutOfBoundsException("Frame has not been written yet"); 00118 00119 //if(frAddr < nextFrAddr-M.length || frAddr >= nextFrAddr || frAddr < 0) 00120 // the first condition has an off by 3 (actually a few off by 00121 // one errors from different places that have accumulated - 00122 // M.length is actually bigger than it should be, M.length is 00123 // always off by one compared to nextFrAddr...) So this fix is 00124 // a hack that ignore a few bugs elsewhere... 00125 if(frAddr < nextFrAddr-M.length-3 || frAddr >= nextFrAddr || frAddr < 0) 00126 return null; 00127 00128 return M[(int)(frAddr % M.length)]; 00129 } 00130 00131 // Set a column of the matrix. 00132 public void setColumn(long frAddr, double[] dat) { 00133 M[(int)(frAddr % M.length)] = dat; 00134 } 00135 00136 public int getRows() { return M[0].length; } 00137 public int getColumns() { return M.length; } 00138 public long getNextFrAddr() { return nextFrAddr; } 00139 }