[Lilith-devel] SF.net SVN: lilith:[167] trunk/lilith
Brought to you by:
huxhorn
From: <hu...@us...> - 2009-02-14 03:22:17
|
Revision: 167 http://lilith.svn.sourceforge.net/lilith/?rev=167&view=rev Author: huxhorn Date: 2009-02-14 02:19:35 +0000 (Sat, 14 Feb 2009) Log Message: ----------- Added FilteringBuffer, FilterJob and SoftReferenceCachingBuffer to main lilith module. Modified Paths: -------------- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java trunk/lilith/src/main/java/de/huxhorn/lilith/swing/taskmanager/TaskManagerPanel.java trunk/lilith-engine/pom.xml trunk/lilith-parent/pom.xml Added Paths: ----------- trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/ trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/SoftReferenceCachingBuffer.java Added: trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java (rev 0) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java 2009-02-14 02:19:35 UTC (rev 167) @@ -0,0 +1,160 @@ +package de.huxhorn.lilith.buffers; + +import de.huxhorn.sulky.buffers.BasicBufferIterator; +import de.huxhorn.sulky.buffers.Buffer; +import de.huxhorn.sulky.buffers.DisposeOperation; +import de.huxhorn.sulky.conditions.Condition; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class FilteringBuffer<E> + implements Buffer<E>, DisposeOperation +{ + private Buffer<E> sourceBuffer; + private Condition condition; + private final List<Long> filteredIndices; + private boolean disposed; + + public FilteringBuffer(Buffer<E> sourceBuffer, Condition condition) + { + this.sourceBuffer = sourceBuffer; + this.condition = condition; + this.filteredIndices = new ArrayList<Long>(); + this.disposed = false; + Thread t = new Thread(new FilterUpdateRunnable(1000)); + t.setDaemon(true); + t.start(); + } + + public E get(long index) + { + long realIndex = getSourceIndex(index); + if(realIndex >= 0) + { + return sourceBuffer.get(realIndex); + } + return null; + } + + public long getSourceIndex(long index) + { + long realIndex = -1; + synchronized(filteredIndices) + { + if(index >= 0 && index < filteredIndices.size()) + { + realIndex = filteredIndices.get((int) index); + } + } + return realIndex; + } + + public long getSize() + { + synchronized(filteredIndices) + { + return filteredIndices.size(); + } + } + + public Iterator<E> iterator() + { + return new BasicBufferIterator<E>(this); + } + + public Buffer<E> getSourceBuffer() + { + return sourceBuffer; + } + + public Condition getCondition() + { + return condition; + } + + public synchronized void dispose() + { + this.disposed = true; + } + + public boolean isDisposed() + { + return disposed; + } + + private class FilterUpdateRunnable + implements Runnable + { + private final Logger logger = LoggerFactory.getLogger(FilterUpdateRunnable.class); + + private int filterDelay; + private long lastFilteredElement; + + public FilterUpdateRunnable(int filterDelay) + { + this.filterDelay = filterDelay; + } + + public void run() + { + for(; ;) + { + if(disposed) + { + break; + } + long currentSize = sourceBuffer.getSize(); + long filterStartIndex = lastFilteredElement; + if(currentSize < lastFilteredElement) + { + filterStartIndex = 0; + synchronized(filteredIndices) + { + filteredIndices.clear(); + } + } + + if(currentSize != lastFilteredElement + 1) + { + //List<Long> newIndices=new ArrayList<Long>(); + for(long i = filterStartIndex; i < currentSize; i++) + { + if(disposed) + { + break; + } + E current = sourceBuffer.get(i); + if(current != null) + { + if(condition != null && condition.isTrue(current)) + { + synchronized(filteredIndices) + { + filteredIndices.add(i); + if(logger.isDebugEnabled()) logger.debug("Added index: {}", i); + } + } + } + lastFilteredElement = i; + } + //if(logger.isInfoEnabled()) logger.info("Added {} indices.", newIndices.size()); + } + try + { + Thread.sleep(filterDelay); + } + catch(InterruptedException e) + { + if(logger.isDebugEnabled()) logger.debug("Interrupted...", e); + return; + } + } + if(logger.isDebugEnabled()) logger.debug("Runnable finished."); + } + } +} Added: trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/SoftReferenceCachingBuffer.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/SoftReferenceCachingBuffer.java (rev 0) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/SoftReferenceCachingBuffer.java 2009-02-14 02:19:35 UTC (rev 167) @@ -0,0 +1,179 @@ +package de.huxhorn.lilith.buffers; + +import de.huxhorn.sulky.buffers.Buffer; +import de.huxhorn.sulky.buffers.DisposeOperation; +import de.huxhorn.sulky.buffers.ResetOperation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SoftReferenceCachingBuffer<E> + implements Buffer<E>, ResetOperation, DisposeOperation +{ + private final Logger logger = LoggerFactory.getLogger(SoftReferenceCachingBuffer.class); + + private static final ReferenceQueue refQueue = new ReferenceQueue(); + + static + { + Thread cleanupThread = new Thread(new ReferenceQueueRunnable(), "ReferenceQueue-Cleanup"); + cleanupThread.setDaemon(true); + cleanupThread.start(); + final Logger logger = LoggerFactory.getLogger(SoftReferenceCachingBuffer.class); + + if(logger.isInfoEnabled()) logger.info("Started thread {}.", cleanupThread); + } + + private Buffer<E> buffer; + + private Map<Long, MySoftReference<E>> cache; + private boolean disposed; + + public SoftReferenceCachingBuffer(Buffer<E> buffer) + { + this.disposed = false; + this.buffer = buffer; + this.cache = new ConcurrentHashMap<Long, MySoftReference<E>>(); + } + + Buffer<E> getWrappedBuffer() + { + return buffer; + } + + public E get(long index) + { + if(disposed) + { + return null; + } + SoftReference<E> softy = cache.get(index); + E result; + if(softy != null) + { + result = softy.get(); + if(result == null) + { + cache.remove(index); + } + else + { + // found in cache... + if(logger.isDebugEnabled()) logger.debug("Retrieved {} from cache.", index); + return result; + } + } + + result = buffer.get(index); + if(result != null) + { + cache.put(index, new MySoftReference<E>(cache, index, result)); + if(logger.isDebugEnabled()) logger.debug("Added {} to cache.", index); + } + return result; + } + + public long getSize() + { + return buffer.getSize(); + } + + public Iterator<E> iterator() + { + return buffer.iterator(); + } + + public void reset() + { + if(buffer instanceof ResetOperation) + { + ResetOperation op = (ResetOperation) buffer; + op.reset(); + } + cache.clear(); + } + + public void dispose() + { + disposed = true; + cache.clear(); + if(buffer instanceof DisposeOperation) + { + DisposeOperation disposeable = (DisposeOperation) buffer; + disposeable.dispose(); + } + } + + public boolean isDisposed() + { + return disposed; + } + + private static class MySoftReference<E> + extends SoftReference<E> + { + private long index; + private Map<Long, MySoftReference<E>> cache; + + public MySoftReference(Map<Long, MySoftReference<E>> cache, long index, E referent) + { + // the following cast is safe since we are not using the content in the reference queue...... + //noinspection unchecked + super(referent, refQueue); + this.index = index; + this.cache = cache; + } + + public long getIndex() + { + return index; + } + + public void removeFromCache() + { + cache.remove(index); + final Logger logger = LoggerFactory.getLogger(SoftReferenceCachingBuffer.class); + if(logger.isDebugEnabled()) logger.debug("Removed {} from cache.", index); + } + } + + private static class ReferenceQueueRunnable + implements Runnable + { + + public void run() + { + + for(; ;) + { + try + { + Reference ref = refQueue.remove(); + if(ref instanceof MySoftReference) + { + MySoftReference reference = (MySoftReference) ref; + reference.removeFromCache(); + } + else + { + final Logger logger = LoggerFactory.getLogger(SoftReferenceCachingBuffer.class); + if(logger.isWarnEnabled()) logger.warn("Unexpected reference!! {}", ref); + } + } + catch(InterruptedException e) + { + final Logger logger = LoggerFactory.getLogger(SoftReferenceCachingBuffer.class); + if(logger.isInfoEnabled()) logger.info("Interrupted ReferenceQueueRunnable..."); + break; + } + } + } + } +} Modified: trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java 2009-02-14 01:05:39 UTC (rev 166) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java 2009-02-14 02:19:35 UTC (rev 167) @@ -17,6 +17,8 @@ */ package de.huxhorn.lilith.swing; +import de.huxhorn.lilith.buffers.FilteringBuffer; +import de.huxhorn.lilith.buffers.SoftReferenceCachingBuffer; import de.huxhorn.lilith.conditions.EventContainsCondition; import de.huxhorn.lilith.conditions.GroovyCondition; import de.huxhorn.lilith.conditions.LoggerEqualsCondition; @@ -34,8 +36,6 @@ import de.huxhorn.lilith.swing.table.model.EventWrapperTableModel; import de.huxhorn.sulky.buffers.Buffer; import de.huxhorn.sulky.buffers.DisposeOperation; -import de.huxhorn.sulky.buffers.FilteringBuffer; -import de.huxhorn.sulky.buffers.SoftReferenceCachingBuffer; import de.huxhorn.sulky.conditions.And; import de.huxhorn.sulky.conditions.Condition; import de.huxhorn.sulky.conditions.Not; Modified: trunk/lilith/src/main/java/de/huxhorn/lilith/swing/taskmanager/TaskManagerPanel.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/taskmanager/TaskManagerPanel.java 2009-02-14 01:05:39 UTC (rev 166) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/swing/taskmanager/TaskManagerPanel.java 2009-02-14 02:19:35 UTC (rev 167) @@ -65,6 +65,8 @@ public TaskManagerPanel(TaskManager<T> taskManager) { + // TODO: add popup menu and cancel on double-click + // TODO: add display of task description taskTableModel = new TaskTableModel<T>(taskManager); setLayout(new BorderLayout()); table = new JTable(taskTableModel); Modified: trunk/lilith-engine/pom.xml =================================================================== --- trunk/lilith-engine/pom.xml 2009-02-14 01:05:39 UTC (rev 166) +++ trunk/lilith-engine/pom.xml 2009-02-14 02:19:35 UTC (rev 167) @@ -49,6 +49,12 @@ </dependency> <dependency> + <groupId>de.huxhorn.sulky</groupId> + <artifactId>de.huxhorn.sulky.conditions</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <scope>compile</scope> Modified: trunk/lilith-parent/pom.xml =================================================================== --- trunk/lilith-parent/pom.xml 2009-02-14 01:05:39 UTC (rev 166) +++ trunk/lilith-parent/pom.xml 2009-02-14 02:19:35 UTC (rev 167) @@ -145,7 +145,7 @@ <artifactId>de.huxhorn.lilith.logback.classic</artifactId> <version>${lilithVersion}</version> </dependency> - + <dependency> <groupId>de.huxhorn.lilith</groupId> <artifactId>de.huxhorn.lilith.logback.appender.multiplex-core</artifactId> @@ -267,6 +267,11 @@ <artifactId>de.huxhorn.sulky.tasks</artifactId> <version>${sulkyVersion}</version> </dependency> + <dependency> + <groupId>de.huxhorn.sulky</groupId> + <artifactId>de.huxhorn.sulky.conditions</artifactId> + <version>${sulkyVersion}</version> + </dependency> <dependency> <groupId>commons-cli</groupId> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |