Author: bpoussin Date: 2014-04-10 20:21:54 +0200 (Thu, 10 Apr 2014) New Revision: 473 Url: http://forge.nuiton.org/projects/nuiton-matrix/repository/revisions/473 Log: rewrite LazyVector to support concurrent modification (CopyOnWrite) Modified: trunk/nuiton-matrix/src/main/java/org/nuiton/math/matrix/LazyVector.java Modified: trunk/nuiton-matrix/src/main/java/org/nuiton/math/matrix/LazyVector.java =================================================================== --- trunk/nuiton-matrix/src/main/java/org/nuiton/math/matrix/LazyVector.java 2014-04-10 13:41:07 UTC (rev 472) +++ trunk/nuiton-matrix/src/main/java/org/nuiton/math/matrix/LazyVector.java 2014-04-10 18:21:54 UTC (rev 473) @@ -1,6 +1,13 @@ package org.nuiton.math.matrix; +import java.util.ConcurrentModificationException; +import java.util.IdentityHashMap; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.commons.collections4.set.MapBackedSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -24,8 +31,8 @@ protected boolean isInitBackend = false; /** reel backend, not initialized since not necessary */ protected Vector backend; - /** vector used when paste is called and backend is not initialized */ - protected Vector copy; + protected AtomicInteger users = new AtomicInteger(); + protected int capacity; public LazyVector(Vector backend, int capacity) { @@ -47,8 +54,6 @@ double result = 0; if (isInitBackend) { result = backend.getMaxOccurrence(); - } else if (copy != null) { - result = copy.getMaxOccurrence(); } return result; } @@ -58,15 +63,13 @@ double result = 0; if (isInitBackend) { result = backend.getValue(pos); - } else if (copy != null) { - result = copy.getValue(pos); } return result; } @Override public void setValue(int pos, double value) { - initBackend(); + prepareBackendForModification(); backend.setValue(pos, value); } @@ -97,31 +100,36 @@ @Override public void paste(Vector source) { - if (!isInitBackend && copy == null) { - copy = source; + if (!isInitBackend && source instanceof LazyVector) { + LazyVector l = ((LazyVector)source); + + l.users.incrementAndGet(); + users = l.users; + isInitBackend = l.isInitBackend; + backend = l.backend; } else { // initialized or already has copy, we need to paste, and not just // reassign copy variable, in case of source Vector is smaller than copy - initBackend(); - pasteToBackend(source); + prepareBackendForModification(); + pasteToBackend(backend, source); } } @Override public void add(Vector v) { - initBackend(); + prepareBackendForModification(); backend.add(v); } @Override public void minus(Vector v) { - initBackend(); + prepareBackendForModification(); backend.minus(v); } @Override public void map(MapFunction f) { - initBackend(); + prepareBackendForModification(); backend.map(f); } @@ -133,9 +141,7 @@ if (size() == v.size()) { if (isInitBackend) { result = v.equals(backend); - } else if (copy != null) { - result = v.equals(copy); - } else if (v instanceof LazyVector && !((LazyVector)v).isInitBackend && ((LazyVector)v).copy == null) { + } else if (v instanceof LazyVector && !((LazyVector)v).isInitBackend) { result = true; } else { result = v.equals(this); @@ -145,36 +151,41 @@ return result; } - protected void initBackend() { + protected void prepareBackendForModification() { + if (users.get() > 0) { + try { + // others LazyVector use this backend, create new backend copy + Vector copy = backend.getClass().newInstance(); + if (isInitBackend) { + copy.init(capacity); + pasteToBackend(copy, backend); + } + backend = copy; + users.decrementAndGet(); + users = new AtomicInteger(); + } catch (Exception eee) { + throw new MatrixException("Can't create new backend Vector", eee); + } + } + if (!isInitBackend) { backend.init(capacity); isInitBackend = true; - if (copy != null) { - pasteToBackend(copy); - } } } /** * Before call this method backend, must be initialized + * @param target * @param copy */ - protected void pasteToBackend(Vector copy) { - if (copy instanceof LazyVector) { - LazyVector l = (LazyVector)copy; - if (l.isInitBackend) { - copy = l.backend; - } else if (l.copy != null) { - copy = l.copy; - } - } - - if (backend.isImplementedPaste(copy)) { - backend.paste(copy); + protected void pasteToBackend(Vector target, Vector copy) { + if (target.isImplementedPaste(copy)) { + target.paste(copy); } else { for (int i=0, max=Math.min(size(), copy.size()); i<max; i++) { double v = copy.getValue(i); - backend.setValue(i, v); + target.setValue(i, v); } } }
participants (1)
-
bpoussin@users.nuiton.org