/*
* Copyright (C) 2008-2015 by Holger Arndt
*
* This file is part of the Universal Java Matrix Package (UJMP).
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* UJMP is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* UJMP 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with UJMP; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package org.ujmp.core.objectmatrix.impl;
import java.io.Flushable;
import java.io.IOException;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import org.ujmp.core.Coordinates;
import org.ujmp.core.Matrix;
import org.ujmp.core.objectmatrix.stub.AbstractSparseObjectMatrix;
public class BufferedObjectMatrix extends AbstractSparseObjectMatrix implements Flushable {
private static final long serialVersionUID = 7750549087897737457L;
private boolean lazy = true;
private Matrix inputBuffer = null;
private SortedSet outputToDoBuffer = Collections
.synchronizedSortedSet(new TreeSet());
private SortedSet inputToDoBuffer = Collections
.synchronizedSortedSet(new TreeSet());
private int outputBufferSize = Integer.MAX_VALUE;
private Matrix original = null;
private Thread writeThread = null;
private Thread readThread = null;
private static final EmptyObject EMPTYOBJECT = new EmptyObject();
public BufferedObjectMatrix(Matrix original) {
super(original.getSize());
this.original = original;
inputBuffer = new DefaultSparseObjectMatrix(original.getSize());
setInputBufferSize(0);
setOutputBufferSize(Integer.MAX_VALUE);
writeThread = new WriteThread();
writeThread.start();
readThread = new ReadThread();
readThread.start();
}
public BufferedObjectMatrix(Matrix original, int outputBufferSize) {
super(original.getSize());
this.original = original;
setInputBufferSize(0);
setOutputBufferSize(outputBufferSize);
}
public BufferedObjectMatrix(Matrix original, int outputBufferSize, int inputBufferSize) {
super(original.getSize());
this.original = original;
setInputBufferSize(inputBufferSize);
setOutputBufferSize(outputBufferSize);
}
public final void clear() {
original.clear();
inputBuffer.clear();
}
public Iterable availableCoordinates() {
throw new RuntimeException("not implemented");
}
public synchronized long[] getSize() {
size = inputBuffer.getSize();
return size;
}
public synchronized Object getObject(long... coordinates) {
Object o = null;
o = inputBuffer.getAsObject(coordinates);
if (o == null) {
if (lazy) {
Coordinates c = Coordinates.wrap(coordinates);
if (!inputToDoBuffer.contains(c)) {
inputToDoBuffer.add(c.clone());
}
} else {
o = original.getAsObject(coordinates);
if (o == null) {
inputBuffer.setAsObject(EMPTYOBJECT, coordinates);
} else {
inputBuffer.setAsObject(o, coordinates);
}
}
} else if (o == EMPTYOBJECT) {
return null;
}
return o;
}
public synchronized long getValueCount() {
return original.getValueCount();
}
public synchronized void setObject(Object value, long... coordinates) {
inputBuffer.setAsObject(value, coordinates);
outputToDoBuffer.add(Coordinates.wrap(coordinates).clone());
}
public synchronized void setInputBufferSize(int numElements) {
if (numElements < 1) {
inputBuffer = new VolatileSparseObjectMatrix(original.getSize());
} else {
inputBuffer = new DefaultSparseObjectMatrix(original.getSize());
}
}
public synchronized void setOutputBufferSize(int numElements) {
try {
flush();
outputToDoBuffer = Collections.synchronizedSortedSet(new TreeSet());
outputBufferSize = numElements;
} catch (IOException e) {
throw new RuntimeException("could not set output buffer", e);
}
}
public synchronized void flush() throws IOException {
while (outputToDoBuffer != null && outputToDoBuffer.size() != 0) {
try {
outputToDoBuffer.wait();
} catch (InterruptedException e) {
throw new RuntimeException("could not flush buffer", e);
}
}
}
public synchronized int getOutputBufferSize() {
return outputBufferSize;
}
class WriteThread extends Thread {
public void run() {
while (true) {
try {
while (outputToDoBuffer != null && !outputToDoBuffer.isEmpty()) {
Coordinates c = outputToDoBuffer.first();
outputToDoBuffer.remove(c);
Object value = inputBuffer.getAsObject(c.getLongCoordinates());
original.setAsObject(value, c.getLongCoordinates());
}
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("error writing to matrix", e);
}
}
}
}
class ReadThread extends Thread {
public void run() {
long t = System.currentTimeMillis();
boolean update = false;
while (true) {
try {
while (inputToDoBuffer != null && !inputToDoBuffer.isEmpty()) {
update = true;
Coordinates c = inputToDoBuffer.first();
inputToDoBuffer.remove(c);
Object value = original.getAsObject(c.getLongCoordinates());
inputBuffer.setAsObject(value, c.getLongCoordinates());
if (System.currentTimeMillis() - t > 500) {
t = System.currentTimeMillis();
fireValueChanged();
}
}
if (update) {
update = false;
fireValueChanged();
}
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
// throw new RuntimeException("error writing to matrix", e);
}
}
}
}
public boolean containsCoordinates(long... coordinates) {
return inputBuffer.containsCoordinates(coordinates)
|| original.containsCoordinates(coordinates);
}
public boolean isReadOnly() {
return original.isReadOnly();
}
}
class EmptyObject {
}
Ads help maintain this website.