Browse Source

new: RandomAccessIntIterator
fix: RandomAccessIterator
fix: AIntList:iterator / sublist
new: IntListUtils#sublist
fix: ListUtils#sublist#iterator - add/set/remove

Ranides Atterwim 10 năm trước cách đây
mục cha
commit
26c7396ba1

+ 103 - 0
assira/src/main/java/net/ranides/assira/collection/iterators/RandomAccessIntIterator.java

@@ -0,0 +1,103 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.iterators;
+
+import java.util.NoSuchElementException;
+
+public abstract class RandomAccessIntIterator implements IntListIterator {
+    
+    private int index;
+    
+    private int last;
+
+    protected abstract int size();
+    
+    protected abstract int get(int index);
+    
+    protected void remove(int index) {
+        throw new UnsupportedOperationException();
+    }
+    
+    protected void add(int index, int value) {
+        throw new UnsupportedOperationException();
+    }
+    
+    protected void set(int index, int value) {
+        throw new UnsupportedOperationException();
+    }
+
+    public RandomAccessIntIterator(int index) {
+        this.index = index;
+        this.last = -1;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return index < size();
+    }
+
+    @Override
+    public boolean hasPrevious() {
+        return index > 0;
+    }
+
+    @Override
+    public int nextInt() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        return get(last = index++);
+    }
+
+    @Override
+    public int previousInt() {
+        if (!hasPrevious()) {
+            throw new NoSuchElementException();
+        }
+        return get(last = --index);
+    }
+
+    @Override
+    public int nextIndex() {
+        return index;
+    }
+
+    @Override
+    public int previousIndex() {
+        return index - 1;
+    }
+
+    @Override
+    public void add(int k) {
+        add(index++, k);
+    }
+
+    @Override
+    public void set(int k) {
+        if (last == -1) {
+            throw new IllegalStateException();
+        }
+        set(last, k);
+    }
+
+    @Override
+    public void remove() {
+        if (last == -1) {
+            throw new IllegalStateException();
+        }
+        remove(last);
+        // If the last operation was a next(), 
+        // we are removing an element *before* us, 
+        // and we must decrease pos correspondingly.
+        if (last < index) {
+            index--;
+        }
+        last = -1;
+    }
+    
+    
+}

+ 40 - 43
assira/src/main/java/net/ranides/assira/collection/iterators/RandomAccessIterator.java

@@ -13,7 +13,7 @@ public abstract class RandomAccessIterator<T> implements ListIterator<T> {
     
     private int index;
     
-    private int cursor;
+    private int last;
 
     protected abstract int size();
     
@@ -31,80 +31,77 @@ public abstract class RandomAccessIterator<T> implements ListIterator<T> {
         throw new UnsupportedOperationException();
     }
     
-    /**
-     * Tworzy iterator wskazujący na pierwszą pozycję w liście
-     */
     public RandomAccessIterator() {
         this(0);
     }
-
-    /**
-     * Tworzy iterator wskazujący na podaną pozycję w liście
-     * @param index
-     */
+    
     public RandomAccessIterator(int index) {
         this.index = index;
-        this.cursor = index;
+        this.last = -1;
     }
 
     @Override
-    public final void set(T value) {
-        if (index == -1) {
-            throw new IllegalStateException("set must be called after next or previous");
-        }
-        set(index, value);
+    public boolean hasNext() {
+        return index < size();
     }
 
     @Override
-    public final void add(T value) {
-        add(index, value);
-        index++;
-        cursor++;
+    public boolean hasPrevious() {
+        return index > 0;
     }
 
     @Override
-    public final void remove() {
-        remove(index);
-        index = - 1;
+    public T next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        return get(last = index++);
     }
 
     @Override
-    public final boolean hasNext() {
-        return cursor < size();
+    public T previous() {
+        if (!hasPrevious()) {
+            throw new NoSuchElementException();
+        }
+        return get(last = --index);
     }
 
     @Override
-    public final T next() {
-        if( cursor >= size() ) { 
-            throw new NoSuchElementException(); 
-        }
-        index = cursor++;
-        return get(index);
+    public int nextIndex() {
+        return index;
     }
 
     @Override
-    public final boolean hasPrevious() {
-        return cursor > 0;
+    public int previousIndex() {
+        return index - 1;
     }
 
     @Override
-    public final T previous() {
-        if( cursor < 1 ) { 
-            throw new NoSuchElementException(); 
-        }
-        index = --cursor;
-        return get(index);
+    public void add(T value) {
+        add(index++, value);
     }
 
     @Override
-    public final int nextIndex() {
-        return cursor;
+    public void set(T value) {
+        if (last == -1) {
+            throw new IllegalStateException();
+        }
+        set(last, value);
     }
 
     @Override
-    public final int previousIndex() {
-        return cursor - 1;
+    public void remove() {
+        if (last == -1) {
+            throw new IllegalStateException();
+        }
+        remove(last);
+        // If the last operation was a next(), 
+        // we are removing an element *before* us, 
+        // and we must decrease pos correspondingly.
+        if (last < index) {
+            index--;
+        }
+        last = -1;
     }
     
-    
 }

+ 103 - 206
assira/src/main/java/net/ranides/assira/collection/lists/AIntList.java

@@ -20,6 +20,7 @@ import net.ranides.assira.collection.arrays.ArrayAllocator;
 import net.ranides.assira.collection.arrays.ArrayUtils;
 import net.ranides.assira.collection.iterators.IntIterator;
 import net.ranides.assira.collection.iterators.IntListIterator;
+import net.ranides.assira.collection.iterators.RandomAccessIntIterator;
 import net.ranides.assira.generic.CompareUtils;
 
 /**
@@ -385,78 +386,52 @@ public abstract class AIntList extends AIntCollection implements IntList, Compar
 
         private static final long serialVersionUID = 2;
 
-        protected final IntList idata;
+        protected final IntList data;
         protected final int begin;
         protected int end;
 
         public SubList(IntList list, int begin, int end) {
-            this.idata = list;
+            this.data = list;
             this.begin = begin;
             this.end = end;
         }
 
-        @Override
-        public int indexOf(int k) {
-            IntListIterator itr = listIterator();
-            int e;
-            while (itr.hasNext()) {
-                e = itr.nextInt();
-                if (((k) == (e))) {
-                    return itr.previousIndex();
-                }
-            }
-            return -1;
-        }
-
-        @Override
-        public int lastIndexOf(int k) {
-            IntListIterator itr = listIterator(size());
-            int e;
-            while (itr.hasPrevious()) {
-                e = itr.previousInt();
-                if (((k) == (e))) {
-                    return itr.nextIndex();
-                }
-            }
-            return -1;
-        }
-
         @Override
         public void add(int index, int k) {
-            checkIndex(index);
-            idata.add(begin + index, k);
+            data.add(begin + index, k);
             end++;
         }
 
         @Override
         public boolean addAll(int index, Collection<? extends Integer> values) {
-            checkIndex(index);
-            end += values.size();
-            return idata.addAll(begin + index, values);
+            if(data.addAll(begin + index, values)) {
+                end += values.size();
+                return true;
+            }
+            return false;
         }
 
         @Override
         public int getInt(int index) {
-            checkIndexElement(index);
-            return idata.getInt(begin + index);
+            return data.getInt(begin + index);
         }
 
         @Override
         public int removeInt(int index) {
-            checkIndexElement(index);
+            int prev = data.removeInt(begin + index);
             end--;
-            return idata.removeInt(begin + index);
+            return prev;
         }
 
         @Override
         public int set(int index, int k) {
-            checkIndexElement(index);
-            return idata.set(begin + index, k);
+            return data.set(begin + index, k);
         }
 
         @Override
         public void clear() {
             removeElements(0, size());
+            end = begin;
         }
 
         @Override
@@ -466,222 +441,144 @@ public abstract class AIntList extends AIntCollection implements IntList, Compar
 
         @Override
         public void getElements(int from, int[] target, int offset, int length) {
-            checkIndex(from);
-            if (from + length > size()) {
-                throw new IndexOutOfBoundsException("End index (" + from + length + ") is greater than list size (" + size() + ")");
-            }
-            idata.getElements(this.begin + from, target, offset, length);
+            data.getElements(this.begin + from, target, offset, length);
         }
 
         @Override
-        public void removeElements(int from, int to) {
-            checkIndex(from);
-            checkIndex(to);
-            idata.removeElements(this.begin + from, this.begin + to);
-            this.end -= (to - from);
+        public void removeElements(int begin, int end) {
+            data.removeElements(this.begin + begin, this.begin + end);
+            this.end -= (end - begin);
         }
 
         @Override
         public void addElements(int index, int a[], int offset, int length) {
-            checkIndex(index);
-            idata.addElements(this.begin + index, a, offset, length);
+            data.addElements(this.begin + index, a, offset, length);
             this.end += length;
         }
 
         @Override
         public IntListIterator listIterator(int index) {
-            checkIndex(index);
             return new SIterator(index);
         }
 
         @Override
         public IntList subList(int from, int to) {
-            checkIndex(from);
-            checkIndex(to);
-            if (from > to) {
-                throw new IllegalArgumentException("Start index (" + from + ") is greater than end index (" + to + ")");
-            }
+            NativeArrayAllocator.ensureFromTo(size(), from, to);
             return new SubList(this, from, to);
         }
 
-        @Override
-        public boolean rem(int k) {
-            int index = indexOf(k);
-            if (index == -1) {
-                return false;
-            }
-            end--;
-            idata.removeInt(begin + index);
-            return true;
-        }
-
-        @Override
-        public boolean remove(Object value) {
-            return rem(((Integer) value).intValue());
-        }
-
         @Override
         public boolean addAll(int index, IntCollection values) {
-            checkIndex(index);
-            end += values.size();
-            return idata.addAll(begin + index, values);
+            if(data.addAll(begin + index, values)) {
+                end += values.size();
+                return true;
+            }
+            return false;
         }
 
         @Override
         public boolean addAll(int index, IntList values) {
-            checkIndex(index);
-            end += values.size();
-            return this.idata.addAll(begin + index, values);
+            if(data.addAll(begin + index, values)) {
+                end += values.size();
+                return true;
+            }
+            return false;
         }
         
         protected final class SIterator implements IntListIterator {
             
-            int pos;
-            int last;
-
-            public SIterator(int pos) {
-                this.pos = pos;
-                this.last = -1;
-            }
-
-            @Override
-            public boolean hasNext() {
-                return pos < size();
-            }
-
-            @Override
-            public boolean hasPrevious() {
-                return pos > 0;
-            }
-
-            @Override
-            public int nextInt() {
-                if (!hasNext()) {
-                    throw new NoSuchElementException();
-                }
-                return idata.getInt(begin + (last = pos++));
-            }
-
-            @Override
-            public int previousInt() {
-                if (!hasPrevious()) {
-                    throw new NoSuchElementException();
-                }
-                return idata.getInt(begin + (last = --pos));
-            }
-
-            @Override
-            public int nextIndex() {
-                return pos;
-            }
-
-            @Override
-            public int previousIndex() {
-                return pos - 1;
-            }
-
-            @Override
-            public void add(int k) {
-                SubList.this.add(pos++, k);
-            }
-
-            @Override
-            public void set(int k) {
-                if (last == -1) {
-                    throw new IllegalStateException();
-                }
-                SubList.this.set(last, k);
-            }
-
-            @Override
-            public void remove() {
-                if (last == -1) {
-                    throw new IllegalStateException();
-                }
-                SubList.this.removeInt(last);
-                // If the last operation was a next(), 
-                // we are removing an element *before* us, 
-                // and we must decrease pos correspondingly.
-                if (last < pos) {
-                    pos--;
-                }
-                last = -1;
-            }
-        }
-    }
-
-    protected class IIterator implements IntListIterator {
-        int pos;
-        int last;
+            private final IntListIterator delegate;
+
+			public SIterator(int index) {
+				this.delegate = data.listIterator(begin + index);
+			}
+
+			@Override
+			public boolean hasNext() {
+				return delegate.nextIndex() < end;
+			}
+
+			@Override
+			public int nextInt() {
+				if(!hasNext()) {
+					throw new NoSuchElementException();
+				}
+				return delegate.nextInt();
+			}
+
+			@Override
+			public boolean hasPrevious() {
+				return delegate.previousIndex() >= begin;
+			}
+
+			@Override
+			public int previousInt() {
+				if(!hasPrevious()) {
+					throw new NoSuchElementException();
+				}
+				return delegate.previousInt();
+			}
+
+			@Override
+			public int nextIndex() {
+				return delegate.nextIndex() - begin;
+			}
+
+			@Override
+			public int previousIndex() {
+				return delegate.previousIndex() - begin;
+			}
+
+			@Override
+			public void remove() {
+				delegate.remove();
+				end--;
+			}
+
+			@Override
+			public void set(int e) {
+				delegate.set(e);
+			}
+
+			@Override
+			public void add(int e) {
+				delegate.add(e);
+				end++;
+			}
+        }
+    }
+
+    protected class IIterator extends RandomAccessIntIterator {
 
         public IIterator(int pos) {
-            this.pos = pos;
-            this.last = -1;
-        }
-        
-        @Override
-        public boolean hasNext() {
-            return pos < size();
-        }
-
-        @Override
-        public boolean hasPrevious() {
-            return pos > 0;
-        }
-
-        @Override
-        public int nextInt() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            return getInt(last = pos++);
+            super(pos);
         }
 
         @Override
-        public int previousInt() {
-            if (!hasPrevious()) {
-                throw new NoSuchElementException();
-            }
-            return getInt(last = --pos);
+        protected int size() {
+            return AIntList.this.size();
         }
 
         @Override
-        public int nextIndex() {
-            return pos;
+        protected int get(int index) {
+            return AIntList.this.get(index);
         }
 
         @Override
-        public int previousIndex() {
-            return pos - 1;
+        protected void set(int index, int value) {
+            AIntList.this.set(index, value);
         }
 
         @Override
-        public void add(int k) {
-            AIntList.this.add(pos++, k);
+        protected void add(int index, int value) {
+            AIntList.this.add(index, value);
         }
 
         @Override
-        public void set(int k) {
-            if (last == -1) {
-                throw new IllegalStateException();
-            }
-            AIntList.this.set(last, k);
+        protected void remove(int index) {
+            AIntList.this.remove(index);
         }
 
-        @Override
-        public void remove() {
-            if (last == -1) {
-                throw new IllegalStateException();
-            }
-            AIntList.this.removeInt(last);
-            // If the last operation was a next(), 
-            // we are removing an element *before* us, 
-            // and we must decrease pos correspondingly.
-            if (last < pos) {
-                pos--;
-            }
-            last = -1;
-        }
     }
     
 }

+ 51 - 0
assira/src/main/java/net/ranides/assira/collection/lists/IntListUtils.java

@@ -10,11 +10,14 @@ package net.ranides.assira.collection.lists;
 import java.util.AbstractList;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.RandomAccess;
 import java.util.function.IntFunction;
 import java.util.function.IntPredicate;
 import java.util.function.IntUnaryOperator;
 import net.ranides.assira.collection.IntCollectionUtils;
+import net.ranides.assira.collection.arrays.NativeArrayAllocator;
 import net.ranides.assira.collection.iterators.IntListIterator;
+import net.ranides.assira.collection.iterators.RandomAccessIntIterator;
 import net.ranides.assira.functional.IntProjectionFunction;
 import net.ranides.assira.functional.ProjectionIntFunction;
 
@@ -186,5 +189,53 @@ public final class IntListUtils {
             }
         };
     } 
+    
+    public static IntList sublist(IntList list, int begin, int end) {
+		NativeArrayAllocator.ensureFromTo(list.size(), begin, end);
+		if(list instanceof RandomAccess) {
+			return new RandomSubList(list, begin, end);
+		} else {
+			return new AIntList.SubList(list, begin, end);
+		}
+	}
+	
+	private static class RandomSubList extends AIntList.SubList implements RandomAccess {
+		
+		public RandomSubList(IntList list, int begin, int end) {
+			super(list, begin, end);
+		}
 
+		@Override
+		public IntListIterator listIterator(int offset) {
+			return new RandomAccessIntIterator(offset){
+				@Override
+				protected int size() {
+					return RandomSubList.this.size();
+				}
+
+				@Override
+				protected int get(int index) {
+					return RandomSubList.this.get(index);
+				}
+
+                @Override
+                protected void set(int index, int value) {
+                    RandomSubList.this.set(index, value);
+                }
+
+                @Override
+                protected void add(int index, int value) {
+                    RandomSubList.this.add(index, value);
+                }
+
+                @Override
+                protected void remove(int index) {
+                    RandomSubList.this.remove(index);
+                }
+				
+			};
+		}
+		
+	}
+	
 }

+ 2 - 1
assira/src/main/java/net/ranides/assira/collection/lists/IntRTList.java

@@ -6,6 +6,7 @@
  */
 package net.ranides.assira.collection.lists;
 
+import java.util.RandomAccess;
 import net.ranides.assira.collection.IntCollection;
 import net.ranides.assira.collection.arrays.ArrayUtils;
 
@@ -17,7 +18,7 @@ import net.ranides.assira.collection.arrays.ArrayUtils;
  * 
  * @author ranides
  */
-public class IntRTList extends AIntList {
+public class IntRTList extends AIntList implements RandomAccess {
 
     private final static int[] EMPTY = new int[0];
 	

+ 26 - 13
assira/src/main/java/net/ranides/assira/collection/lists/ListUtils.java

@@ -127,8 +127,6 @@ public final class ListUtils {
         };
     }  
 	
-	// @todo (assira #1) IntListUtils#sublist
-	
 	public static <T> List<T> sublist(List<T> list, int begin, int end) {
 		NativeArrayAllocator.ensureFromTo(list.size(), begin, end);
 		if(list instanceof RandomAccess) {
@@ -156,6 +154,23 @@ public final class ListUtils {
 				protected T get(int index) {
 					return RandomSubList.this.get(index);
 				}
+
+                @Override
+                protected void set(int index, T value) {
+                    RandomSubList.this.set(index, value);
+                }
+
+                @Override
+                protected void add(int index, T value) {
+                    RandomSubList.this.add(index, value);
+                }
+
+                @Override
+                protected void remove(int index) {
+                    RandomSubList.this.remove(index);
+                }
+                
+                
 				
 			};
 		}
@@ -166,25 +181,25 @@ public final class ListUtils {
 
         private static final long serialVersionUID = 2;
 
-        protected final List<T> that;
+        protected final List<T> data;
         protected final int begin;
         protected int end;
 
         public SubList(List<T> list, int begin, int end) {
-            this.that = list;
+            this.data = list;
             this.begin = begin;
             this.end = end;
         }
 
         @Override
         public void add(int index, T value) {
-            that.add(begin + index, value);
+            data.add(begin + index, value);
             end++;
         }
 
         @Override
         public boolean addAll(int index, Collection<? extends T> values) {
-            if( that.addAll(begin + index, values) ) {
+            if( data.addAll(begin + index, values) ) {
 				end += values.size();
 				return true;
 			}
@@ -193,19 +208,19 @@ public final class ListUtils {
 
         @Override
         public T get(int index) {
-            return that.get(begin + index);
+            return data.get(begin + index);
         }
 
         @Override
         public T remove(int index) {
-            T prev = that.remove(begin + index);
+            T prev = data.remove(begin + index);
 			end--;
 			return prev;
         }
 
         @Override
         public T set(int index, T value) {
-            return that.set(begin + index, value);
+            return data.set(begin + index, value);
         }
 
         @Override
@@ -227,7 +242,7 @@ public final class ListUtils {
         @Override
         public List<T> subList(int from, int to) {
 			NativeArrayAllocator.ensureFromTo(size(), from, to);
-            return new SubList(this, from, to);
+            return new SubList<>(this, from, to);
         }
 
         protected final class SIterator implements ListIterator<T> {
@@ -235,7 +250,7 @@ public final class ListUtils {
 			private final ListIterator<T> delegate;
 
 			public SIterator(int index) {
-				this.delegate = that.listIterator(begin + index);
+				this.delegate = data.listIterator(begin + index);
 			}
 
 			@Override
@@ -291,8 +306,6 @@ public final class ListUtils {
 				end++;
 			}
 			
-			
-			
         }
     }
 

+ 2 - 1
assira/src/main/java/net/ranides/assira/collection/lists/RTList.java

@@ -10,6 +10,7 @@ import java.io.Serializable;
 import java.util.AbstractList;
 import java.util.Collection;
 import java.util.List;
+import java.util.RandomAccess;
 import net.ranides.assira.collection.arrays.ArrayUtils;
 
 /**
@@ -25,7 +26,7 @@ import net.ranides.assira.collection.arrays.ArrayUtils;
  * @author ranides
  */
 @SuppressWarnings("unchecked")
-public class RTList<T> extends AbstractList<T> implements Serializable {
+public class RTList<T> extends AbstractList<T> implements RandomAccess, Serializable {
 	
 	private static final long serialVersionUID = 1L;
 

+ 456 - 457
assira/src/main/java/net/ranides/assira/events/EventLock.java

@@ -1,457 +1,456 @@
-/*
- *  @author Ranides Atterwim <ranides@gmail.com>
- *  @copyright Ranides Atterwim
- *  @license WTFPL
- *  @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.events;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import net.ranides.assira.annotations.Meta;
-import net.ranides.assira.trace.LoggerUtils;
-import org.slf4j.Logger;
-
-/**
- * Klasa pozwalająca na synchroniczną obsługę zdarzeń. Pozwala wstrzymać wykonanie
- * bieżącego wątku i oczekiwać, aż do wskazanego {@link EventRouter}'a dotrze
- * zdarzenie określonego typu.
- * <p>
- * Zależnie od rodzaju implementacji, klasa może oferować usługi o różnym stopniu
- * dokładności i bezpieczeństwa.
- * </p>
- * <p>Najsilniejsze gwarancje, to możliwość obsługi wszystkich zdarzeń określonego
- * rodzaju bez ryzyka pominięcia żadnego. Nawet jeśli jedno lub więcej zdarzeń
- * nastąpiło przed (lub pomiędzy) wywołaniem metody {@link #waitForEvent}, to zostanie
- * ono dostarczone. Gwarantowana jest również prawidłowa kolejność dostarczenia
- * komunikatów przez kolejne wywołania metod blokujących. Implementacje "silne"
- * mają duże wymagania pamięciowe, w ekstremalnym przypadku mogą spowodować
- * przepełnienie sterty, jeśli program zostanie zalany komunikatami.
- * </p>
- * <p>
- * "Słaby {@code EventLock}" daje gwarancje, że metody {@link #waitForEvent} nie
- * będą blokować, jeśli pomiędzy ich wywołaniami (albo przed wywołaniem) wystąpiło
- * obserwowane zdarzenie. Nie dają jednak gwarancji dostarczenia wszystkich
- * komunikatów - część z nich może być utracona/pominięta, w przypadku wysokiego
- * obciążenia. Słaby {@code EventLock} udostępnia informację o ilości zgubionych
- * komunikatów. Jego zaletą jest znacznie mniejsze zużycie pamięci oraz brak podatności
- * na przeciążenie aplikacji.
- * </p>
- * <p>
- * "Niebezpieczny {@code EventLock}" nie oferuje żadnych gwarancji. Co więcej:
- * metody {@link #waitForEvent} zawsze blokują, a jako wynik zwracają tylko i
- * wyłącznie wydarzenie, które nastąpiło w czasie blokady. Z tego powodu jest
- * silnie podatny na <i>race condition</i>. Jego zaletą jest niemal całkowity
- * brak obciążenia pamięci oraz procesora. Z tego powodu może być z powodzeniem
- * używany do obserwacji zdarzeń przychodzących w bardzo dużo odstępach (względem czasu
- * obsługi) bez obaw o wydajność aplikacji.
- * </p>
- * @author ranides
- * 
- * @todo (assira #1) EventStream zamiast EventLock
- */
-public abstract class EventLock<E extends Event> {
-    
-    private static final int LOG_BATCH = 100;
-    
-    /**
-     * Zwraca liczbę komunikatów zgubionych przez cały czas istnienia obiektu.
-     * @return 
-     */
-    public int discarded() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Zwraca liczbę wszystkich otrzymanych komunikatów przez cały czas istnienia obiektu
-     * (w tym komuniaktów zgubionych).
-     * @return 
-     */
-    public int counter() {
-        throw new UnsupportedOperationException();
-    }
-    
-    /**
-     * Zwraca liczbę aktualnie oczekujących komunikatów.
-     * @return 
-     */
-    public int pending() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Niszczy obiekt {@code EventLock} i zwalnia wszystkie zasoby.
-     */
-    public abstract void release();
-
-    /**
-     * Resetuje stan obiektu - jeśli {@code EventLock} przechowywał w kolejce
-     * nieobsłużone zdarzenia - są one usuwane. Wywołanie funkcji {@code reset}
-     * pomiędzy dwoma wywołaniami metody {@code wait} może spowodować, że część zdarzeń,
-     * którymi {@code EventLock} był zainteresowany zostanie utracona.
-     */
-    public abstract void reset();
-
-    /**
-     * Metoda blokująca: wstrzymuje wykonanie bieżącego wątku do momentu, aż
-     * do obserwowanego {@code EventRouter}'a dotrze dowolne zdarzenie oczekiwane
-     * przez {@code EventLock} lub wystąpi wyjątek {@code InterruptedException}.
-     * Zobacz opis klasy {@link EventLock} aby poznać szczegóły.
-     * @return oczekiwane zdarzenie
-     * @throws InterruptedException
-     */
-    public abstract E waitForEvent() throws InterruptedException;
-
-    /**
-     * Metoda blokująca: wstrzymuje wykonanie bieżącego wątku do momentu, aż
-     * do obserwowanego {@code EventRouter}'a dotrze dowolne zdarzenie oczekiwane
-     * przez {@code EventLock}, wystąpi wyjątek {@code InterruptedException}, lub
-     * minie podany czas.
-     * Zobacz opis klasy {@link EventLock} aby poznać szczegóły.
-     * @param timeout
-     * @return oczekiwane zdarzenie
-     * @throws InterruptedException
-     */
-    public abstract E waitForEvent(long timeout) throws InterruptedException;
-
-    /**
-     * Wersja oczekująca na zdarzenie konkretnego rodzaju. Zachowuje się identycznie
-     * jak {@link #waitForEvent()}, z tą różnicą, że reaguje na mniejszy zakres
-     * zdarzeń - zawężony tylko do podanej klasy oraz jej pochodnych.
-     * <p>
-     * Metoda przydatna szczególnie wtedy, gdy utworzony obiekt {@code EventLock}
-     * reaguje na bardzo ogólną klasę zdarzeń, a użytkownik w danym momencie chce
-     * wstrzymać wykonanie w oczekiwaniu na zdarzenie bardziej szczegółowe.
-     * </p>
-     * @param <T>
-     * @param event
-     * @return oczekiwane zdarzenie lub {@code null}, jeśli minął {@code timeout}
-     * @throws InterruptedException
-     */
-    public abstract <T extends E> T waitForEvent(Class<T> event) throws InterruptedException;
-
-    /**
-     * Wersja oczekująca na zdarzenie konkretnego rodzaju. Zachowuje się identycznie
-     * jak {@link #waitForEvent(long timeout)}, z tą różnicą, że reaguje na mniejszy zakres
-     * zdarzeń - zawężony tylko do podanej klasy oraz jej pochodnych.
-     * <p>
-     * Metoda przydatna szczególnie wtedy, gdy utworzony obiekt {@code EventLock}
-     * reaguje na bardzo ogólną klasę zdarzeń, a użytkownik w danym momencie chce
-     * wstrzymać wykonanie w oczekiwaniu na zdarzenie bardziej szczegółowe.
-     * </p>
-     * @param <T>
-     * @param event
-     * @param timeout
-     * @return oczekiwane zdarzenie lub {@code null}, jeśli minął {@code timeout}
-     * @throws InterruptedException
-     */
-    public abstract <T extends E> T waitForEvent(Class<T> event, long timeout) throws InterruptedException;
-
-
-
-    /**
-     * Metoda tworzy silny {@code EventLock} - szczegóły "silnego kontraktu"
-     * są w opisie klasy {@link EventLock}).
-     * <p>
-     * Jeśli obiekt nie jest już potrzebny, musi zostać zwolniony za pomocą metody {@link #release()}
-     * </p>
-     * @param event
-     * @param router
-     * @return
-     */
-    public static <EE extends Event> EventLock<EE> lock(Class<EE> event, EventRouter router) {
-        return lock(event, router, Integer.MAX_VALUE);
-    }
-
-    /**
-     * Metoda tworzy słaby {@code EventLock} - szczegóły "słabego kontraktu"
-     * są w opisie klasy {@link EventLock}).
-     * <p>
-     * Jeśli obiekt nie jest już potrzebny, musi zostać zwolniony za pomocą metody {@link #release()}
-     * </p>
-     * @param event
-     * @param router
-     * @param capacity
-     * @return
-     */
-    public static <EE extends Event> EventLock<EE> lock(Class<EE> event, EventRouter router, int capacity) {
-        QueEventLock<EE> lock = new QueEventLock<>(event, router, capacity);
-        router.addEventListener(event, lock);
-        return lock;
-    }
-
-    /**
-     * Metoda tworzy silny {@code EventLock}, który może zostać wykorzystany tylko raz
-     * - szczegóły "silnego kontraktu" są w opisie klasy {@link EventLock}).
-     * <p>
-     * Po zakończeniu metody {@code waitForEvent} obiekt sam automatycznie
-     * zwalnia wszystkie zasoby i przestaje być funcjonalny.
-     * </p>
-     * @param event
-     * @param router
-     * @return
-     */
-    public static <EE extends Event> EventLock<EE> singleLock(Class<EE> event, EventRouter router) {
-        return singleLock(event, router, Integer.MAX_VALUE);
-    }
-    
-    /**
-     * Metoda tworzy słaby {@code EventLock}, który może zostać wykorzystany tylko raz
-     * - szczegóły "słabego kontraktu" są w opisie klasy {@link EventLock}).
-     * <p>
-     * Po zakończeniu metody {@code waitForEvent} obiekt sam automatycznie
-     * zwalnia wszystkie zasoby i przestaje być funcjonalny.
-     * </p>
-     * @param event
-     * @param router
-     * @return
-     */
-    public static <EE extends Event> EventLock<EE> singleLock(Class<EE> event, EventRouter router, int capacity) {
-        SingleLock<EE> lock = new SingleLock<>(event, router, capacity);
-        router.addEventListener(event, lock);
-        return lock;
-    }
-
-    /**
-     * Metoda tworzy niebezpieczny {@code EventLock} - szczegóły "niebezpiecznego kontraktu"
-     * są w opisie klasy {@link EventLock}).
-     * <p>
-     * Jeśli obiekt nie jest już potrzebny, musi zostać zwolniony za pomocą metody {@link #release()}
-     * </p>
-     * @param event
-     * @param router
-     * @return
-     */
-    @Meta.Unsafe
-    public static <EE extends Event> EventLock<EE> unsafeLock(Class<EE> event, EventRouter router) {
-        UnsafeEventLock<EE> lock = new UnsafeEventLock<>(event, router);
-        router.addEventListener(event, lock);
-        return lock;
-    }
-
-    private static class UnsafeEventLock<EE extends Event> extends EventLock<EE> implements EventListener<EE> {
-
-        private final Class<? extends EE> observed;
-        private final EventRouter router;
-        private volatile EE hit;
-
-        public UnsafeEventLock(Class<? extends EE> event, EventRouter router) {
-                super();
-                this.observed = event;
-                this.router = router;
-            }
-
-        @Override
-        public void handleEvent(EE event) {
-            synchronized (this) {
-                hit = event;
-                this.notifyAll();
-            }
-        }
-
-        @Override
-        public EE waitForEvent() throws InterruptedException {
-            synchronized (this) {
-                while (hit==null) { this.wait(); }
-                EE result = hit;
-                hit = null;
-                return result;
-            }
-        }
-
-        @Override
-        public EE waitForEvent(long timeout) throws InterruptedException {
-            long end = System.currentTimeMillis() + timeout;
-            long rem = timeout;
-            synchronized (this) {
-                while (hit==null && rem>0) {
-                    this.wait(rem);
-                    rem = end - System.currentTimeMillis();
-                }
-                EE result = hit;
-                hit = null;
-                return result;
-            }
-        }
-
-        @Override
-        public <T extends EE> T waitForEvent(Class<T> event) throws InterruptedException {
-            synchronized (this) {
-                while( !event.isInstance(hit) ) { this.wait(); }
-                Event ret = hit;
-                hit = null;
-                return event.cast(ret);
-            }
-        }
-
-        @Override
-        public <T extends EE> T waitForEvent(Class<T> event, long timeout) throws InterruptedException {
-            long end = System.currentTimeMillis() + timeout;
-            long rem = timeout;
-            synchronized (this) {
-                while( !event.isInstance(hit) && rem>0) {
-                    this.wait(rem);
-                    rem = end - System.currentTimeMillis();
-                }
-                EE ret = hit;
-                hit = null;
-                return event.cast(ret);
-            }
-        }
-
-        @Override
-        public void reset() {
-            hit = null;
-        }
-
-        @Override
-        public void release() {
-            router.removeEventListener(observed, this);
-        }
-
-    }
-    
-    private static class QueEventLock<EE extends Event> extends EventLock<EE> implements EventListener<EE> {
-
-        private static final Logger LOGGER = LoggerUtils.getLogger();
-
-        private final Class<? extends EE> observed;
-        private final EventRouter router;
-        private final BlockingQueue<EE> events;
-        private int discarded;
-        private int processed;
-
-        public QueEventLock(Class<? extends EE> event, EventRouter router, int capacity) {
-            this.observed = event;
-            this.router = router;
-            this.processed = 0;
-            this.discarded = 0;
-            this.events = new LinkedBlockingQueue<>(capacity);
-        }
-
-        @Override
-        public EE waitForEvent() throws InterruptedException {
-            return events.take();
-        }
-
-        @Override
-        public EE waitForEvent(long timeout) throws InterruptedException {
-            return events.poll(timeout, TimeUnit.MILLISECONDS);
-        }
-
-        @Override
-        public <T extends EE> T waitForEvent(Class<T> event) throws InterruptedException {
-            while(true) {
-                EE recent = events.take();
-                if( event.isInstance(recent) ) {
-                    return event.cast(recent);
-                }
-            }
-        }
-
-        @Override
-        public <T extends EE> T waitForEvent(Class<T> event, long timeout) throws InterruptedException {
-            long end = System.currentTimeMillis() + timeout;
-            long rem = timeout;
-            while(rem > 0) {
-                EE recent = events.poll(rem, TimeUnit.MILLISECONDS);
-                if( event.isInstance(recent) ) {
-                    return event.cast(recent);
-                }
-                rem = end - System.currentTimeMillis();
-            }
-            return null;
-        }
-
-        @Override
-        public void release() {
-            LOGGER.trace("overall processed={}", processed);
-            if( discarded > 0 ) {
-                LOGGER.warn("overall discarded={}",discarded);
-            }
-            router.removeEventListener(observed, this);
-        }
-
-        @Override
-        public void reset() {
-            events.clear();
-        }
-
-        @Override
-        public void handleEvent(EE event) {
-            processed++;
-            while( !events.offer(event) ) { 
-                Event ignored = events.poll();
-                discarded++;
-                if( 0 == (processed % LOG_BATCH) ) {
-                    LOGGER.warn("events flood. processed={} discarded={} event={}", processed, discarded, ignored);
-                }
-            }
-        }
-
-        @Override
-        public int discarded() {
-            return discarded;
-        }
-
-        @Override
-        public int counter() {
-            return processed;
-        }
-
-        @Override
-        public int pending() {
-            return events.size();
-        }
-
-    }
-    
-    private static class SingleLock<EE extends Event> extends QueEventLock<EE> {
-
-        public <T extends EE> SingleLock(Class<T> event, EventRouter router, int capacity) {
-            super(event, router, capacity);
-        }
-        
-        @Override
-        public EE waitForEvent() throws InterruptedException {
-            try {
-                return super.waitForEvent();
-            } finally {
-                release();
-            }
-        }
-
-        @Override
-        public <T extends EE> T waitForEvent(Class<T> event) throws InterruptedException {
-            try {
-                return super.waitForEvent(event);
-            } finally {
-                release();
-            }
-        }
-
-        @Override
-        public <T extends EE> T waitForEvent(Class<T> event, long timeout) throws InterruptedException {
-            try {
-                return super.waitForEvent(event, timeout);
-            } finally {
-                release();
-            }
-        }
-
-        @Override
-        public EE waitForEvent(long timeout) throws InterruptedException {
-            try {
-                return super.waitForEvent(timeout);
-            } finally {
-                release();
-            }
-        }
-        
-        
-        
-    }
-
-}
+/*
+ *  @author Ranides Atterwim <ranides@gmail.com>
+ *  @copyright Ranides Atterwim
+ *  @license WTFPL
+ *  @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.events;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import net.ranides.assira.annotations.Meta;
+import net.ranides.assira.trace.LoggerUtils;
+import org.slf4j.Logger;
+
+/**
+ * Klasa pozwalająca na synchroniczną obsługę zdarzeń. Pozwala wstrzymać wykonanie
+ * bieżącego wątku i oczekiwać, aż do wskazanego {@link EventRouter}'a dotrze
+ * zdarzenie określonego typu.
+ * <p>
+ * Zależnie od rodzaju implementacji, klasa może oferować usługi o różnym stopniu
+ * dokładności i bezpieczeństwa.
+ * </p>
+ * <p>Najsilniejsze gwarancje, to możliwość obsługi wszystkich zdarzeń określonego
+ * rodzaju bez ryzyka pominięcia żadnego. Nawet jeśli jedno lub więcej zdarzeń
+ * nastąpiło przed (lub pomiędzy) wywołaniem metody {@link #waitForEvent}, to zostanie
+ * ono dostarczone. Gwarantowana jest również prawidłowa kolejność dostarczenia
+ * komunikatów przez kolejne wywołania metod blokujących. Implementacje "silne"
+ * mają duże wymagania pamięciowe, w ekstremalnym przypadku mogą spowodować
+ * przepełnienie sterty, jeśli program zostanie zalany komunikatami.
+ * </p>
+ * <p>
+ * "Słaby {@code EventLock}" daje gwarancje, że metody {@link #waitForEvent} nie
+ * będą blokować, jeśli pomiędzy ich wywołaniami (albo przed wywołaniem) wystąpiło
+ * obserwowane zdarzenie. Nie dają jednak gwarancji dostarczenia wszystkich
+ * komunikatów - część z nich może być utracona/pominięta, w przypadku wysokiego
+ * obciążenia. Słaby {@code EventLock} udostępnia informację o ilości zgubionych
+ * komunikatów. Jego zaletą jest znacznie mniejsze zużycie pamięci oraz brak podatności
+ * na przeciążenie aplikacji.
+ * </p>
+ * <p>
+ * "Niebezpieczny {@code EventLock}" nie oferuje żadnych gwarancji. Co więcej:
+ * metody {@link #waitForEvent} zawsze blokują, a jako wynik zwracają tylko i
+ * wyłącznie wydarzenie, które nastąpiło w czasie blokady. Z tego powodu jest
+ * silnie podatny na <i>race condition</i>. Jego zaletą jest niemal całkowity
+ * brak obciążenia pamięci oraz procesora. Z tego powodu może być z powodzeniem
+ * używany do obserwacji zdarzeń przychodzących w bardzo dużo odstępach (względem czasu
+ * obsługi) bez obaw o wydajność aplikacji.
+ * </p>
+ * @author ranides
+ * 
+ */
+public abstract class EventLock<E extends Event> {
+    
+    private static final int LOG_BATCH = 100;
+    
+    /**
+     * Zwraca liczbę komunikatów zgubionych przez cały czas istnienia obiektu.
+     * @return 
+     */
+    public int discarded() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Zwraca liczbę wszystkich otrzymanych komunikatów przez cały czas istnienia obiektu
+     * (w tym komuniaktów zgubionych).
+     * @return 
+     */
+    public int counter() {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * Zwraca liczbę aktualnie oczekujących komunikatów.
+     * @return 
+     */
+    public int pending() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Niszczy obiekt {@code EventLock} i zwalnia wszystkie zasoby.
+     */
+    public abstract void release();
+
+    /**
+     * Resetuje stan obiektu - jeśli {@code EventLock} przechowywał w kolejce
+     * nieobsłużone zdarzenia - są one usuwane. Wywołanie funkcji {@code reset}
+     * pomiędzy dwoma wywołaniami metody {@code wait} może spowodować, że część zdarzeń,
+     * którymi {@code EventLock} był zainteresowany zostanie utracona.
+     */
+    public abstract void reset();
+
+    /**
+     * Metoda blokująca: wstrzymuje wykonanie bieżącego wątku do momentu, aż
+     * do obserwowanego {@code EventRouter}'a dotrze dowolne zdarzenie oczekiwane
+     * przez {@code EventLock} lub wystąpi wyjątek {@code InterruptedException}.
+     * Zobacz opis klasy {@link EventLock} aby poznać szczegóły.
+     * @return oczekiwane zdarzenie
+     * @throws InterruptedException
+     */
+    public abstract E waitForEvent() throws InterruptedException;
+
+    /**
+     * Metoda blokująca: wstrzymuje wykonanie bieżącego wątku do momentu, aż
+     * do obserwowanego {@code EventRouter}'a dotrze dowolne zdarzenie oczekiwane
+     * przez {@code EventLock}, wystąpi wyjątek {@code InterruptedException}, lub
+     * minie podany czas.
+     * Zobacz opis klasy {@link EventLock} aby poznać szczegóły.
+     * @param timeout
+     * @return oczekiwane zdarzenie
+     * @throws InterruptedException
+     */
+    public abstract E waitForEvent(long timeout) throws InterruptedException;
+
+    /**
+     * Wersja oczekująca na zdarzenie konkretnego rodzaju. Zachowuje się identycznie
+     * jak {@link #waitForEvent()}, z tą różnicą, że reaguje na mniejszy zakres
+     * zdarzeń - zawężony tylko do podanej klasy oraz jej pochodnych.
+     * <p>
+     * Metoda przydatna szczególnie wtedy, gdy utworzony obiekt {@code EventLock}
+     * reaguje na bardzo ogólną klasę zdarzeń, a użytkownik w danym momencie chce
+     * wstrzymać wykonanie w oczekiwaniu na zdarzenie bardziej szczegółowe.
+     * </p>
+     * @param <T>
+     * @param event
+     * @return oczekiwane zdarzenie lub {@code null}, jeśli minął {@code timeout}
+     * @throws InterruptedException
+     */
+    public abstract <T extends E> T waitForEvent(Class<T> event) throws InterruptedException;
+
+    /**
+     * Wersja oczekująca na zdarzenie konkretnego rodzaju. Zachowuje się identycznie
+     * jak {@link #waitForEvent(long timeout)}, z tą różnicą, że reaguje na mniejszy zakres
+     * zdarzeń - zawężony tylko do podanej klasy oraz jej pochodnych.
+     * <p>
+     * Metoda przydatna szczególnie wtedy, gdy utworzony obiekt {@code EventLock}
+     * reaguje na bardzo ogólną klasę zdarzeń, a użytkownik w danym momencie chce
+     * wstrzymać wykonanie w oczekiwaniu na zdarzenie bardziej szczegółowe.
+     * </p>
+     * @param <T>
+     * @param event
+     * @param timeout
+     * @return oczekiwane zdarzenie lub {@code null}, jeśli minął {@code timeout}
+     * @throws InterruptedException
+     */
+    public abstract <T extends E> T waitForEvent(Class<T> event, long timeout) throws InterruptedException;
+
+
+
+    /**
+     * Metoda tworzy silny {@code EventLock} - szczegóły "silnego kontraktu"
+     * są w opisie klasy {@link EventLock}).
+     * <p>
+     * Jeśli obiekt nie jest już potrzebny, musi zostać zwolniony za pomocą metody {@link #release()}
+     * </p>
+     * @param event
+     * @param router
+     * @return
+     */
+    public static <EE extends Event> EventLock<EE> lock(Class<EE> event, EventRouter router) {
+        return lock(event, router, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Metoda tworzy słaby {@code EventLock} - szczegóły "słabego kontraktu"
+     * są w opisie klasy {@link EventLock}).
+     * <p>
+     * Jeśli obiekt nie jest już potrzebny, musi zostać zwolniony za pomocą metody {@link #release()}
+     * </p>
+     * @param event
+     * @param router
+     * @param capacity
+     * @return
+     */
+    public static <EE extends Event> EventLock<EE> lock(Class<EE> event, EventRouter router, int capacity) {
+        QueEventLock<EE> lock = new QueEventLock<>(event, router, capacity);
+        router.addEventListener(event, lock);
+        return lock;
+    }
+
+    /**
+     * Metoda tworzy silny {@code EventLock}, który może zostać wykorzystany tylko raz
+     * - szczegóły "silnego kontraktu" są w opisie klasy {@link EventLock}).
+     * <p>
+     * Po zakończeniu metody {@code waitForEvent} obiekt sam automatycznie
+     * zwalnia wszystkie zasoby i przestaje być funcjonalny.
+     * </p>
+     * @param event
+     * @param router
+     * @return
+     */
+    public static <EE extends Event> EventLock<EE> singleLock(Class<EE> event, EventRouter router) {
+        return singleLock(event, router, Integer.MAX_VALUE);
+    }
+    
+    /**
+     * Metoda tworzy słaby {@code EventLock}, który może zostać wykorzystany tylko raz
+     * - szczegóły "słabego kontraktu" są w opisie klasy {@link EventLock}).
+     * <p>
+     * Po zakończeniu metody {@code waitForEvent} obiekt sam automatycznie
+     * zwalnia wszystkie zasoby i przestaje być funcjonalny.
+     * </p>
+     * @param event
+     * @param router
+     * @return
+     */
+    public static <EE extends Event> EventLock<EE> singleLock(Class<EE> event, EventRouter router, int capacity) {
+        SingleLock<EE> lock = new SingleLock<>(event, router, capacity);
+        router.addEventListener(event, lock);
+        return lock;
+    }
+
+    /**
+     * Metoda tworzy niebezpieczny {@code EventLock} - szczegóły "niebezpiecznego kontraktu"
+     * są w opisie klasy {@link EventLock}).
+     * <p>
+     * Jeśli obiekt nie jest już potrzebny, musi zostać zwolniony za pomocą metody {@link #release()}
+     * </p>
+     * @param event
+     * @param router
+     * @return
+     */
+    @Meta.Unsafe
+    public static <EE extends Event> EventLock<EE> unsafeLock(Class<EE> event, EventRouter router) {
+        UnsafeEventLock<EE> lock = new UnsafeEventLock<>(event, router);
+        router.addEventListener(event, lock);
+        return lock;
+    }
+
+    private static class UnsafeEventLock<EE extends Event> extends EventLock<EE> implements EventListener<EE> {
+
+        private final Class<? extends EE> observed;
+        private final EventRouter router;
+        private volatile EE hit;
+
+        public UnsafeEventLock(Class<? extends EE> event, EventRouter router) {
+                super();
+                this.observed = event;
+                this.router = router;
+            }
+
+        @Override
+        public void handleEvent(EE event) {
+            synchronized (this) {
+                hit = event;
+                this.notifyAll();
+            }
+        }
+
+        @Override
+        public EE waitForEvent() throws InterruptedException {
+            synchronized (this) {
+                while (hit==null) { this.wait(); }
+                EE result = hit;
+                hit = null;
+                return result;
+            }
+        }
+
+        @Override
+        public EE waitForEvent(long timeout) throws InterruptedException {
+            long end = System.currentTimeMillis() + timeout;
+            long rem = timeout;
+            synchronized (this) {
+                while (hit==null && rem>0) {
+                    this.wait(rem);
+                    rem = end - System.currentTimeMillis();
+                }
+                EE result = hit;
+                hit = null;
+                return result;
+            }
+        }
+
+        @Override
+        public <T extends EE> T waitForEvent(Class<T> event) throws InterruptedException {
+            synchronized (this) {
+                while( !event.isInstance(hit) ) { this.wait(); }
+                Event ret = hit;
+                hit = null;
+                return event.cast(ret);
+            }
+        }
+
+        @Override
+        public <T extends EE> T waitForEvent(Class<T> event, long timeout) throws InterruptedException {
+            long end = System.currentTimeMillis() + timeout;
+            long rem = timeout;
+            synchronized (this) {
+                while( !event.isInstance(hit) && rem>0) {
+                    this.wait(rem);
+                    rem = end - System.currentTimeMillis();
+                }
+                EE ret = hit;
+                hit = null;
+                return event.cast(ret);
+            }
+        }
+
+        @Override
+        public void reset() {
+            hit = null;
+        }
+
+        @Override
+        public void release() {
+            router.removeEventListener(observed, this);
+        }
+
+    }
+    
+    private static class QueEventLock<EE extends Event> extends EventLock<EE> implements EventListener<EE> {
+
+        private static final Logger LOGGER = LoggerUtils.getLogger();
+
+        private final Class<? extends EE> observed;
+        private final EventRouter router;
+        private final BlockingQueue<EE> events;
+        private int discarded;
+        private int processed;
+
+        public QueEventLock(Class<? extends EE> event, EventRouter router, int capacity) {
+            this.observed = event;
+            this.router = router;
+            this.processed = 0;
+            this.discarded = 0;
+            this.events = new LinkedBlockingQueue<>(capacity);
+        }
+
+        @Override
+        public EE waitForEvent() throws InterruptedException {
+            return events.take();
+        }
+
+        @Override
+        public EE waitForEvent(long timeout) throws InterruptedException {
+            return events.poll(timeout, TimeUnit.MILLISECONDS);
+        }
+
+        @Override
+        public <T extends EE> T waitForEvent(Class<T> event) throws InterruptedException {
+            while(true) {
+                EE recent = events.take();
+                if( event.isInstance(recent) ) {
+                    return event.cast(recent);
+                }
+            }
+        }
+
+        @Override
+        public <T extends EE> T waitForEvent(Class<T> event, long timeout) throws InterruptedException {
+            long end = System.currentTimeMillis() + timeout;
+            long rem = timeout;
+            while(rem > 0) {
+                EE recent = events.poll(rem, TimeUnit.MILLISECONDS);
+                if( event.isInstance(recent) ) {
+                    return event.cast(recent);
+                }
+                rem = end - System.currentTimeMillis();
+            }
+            return null;
+        }
+
+        @Override
+        public void release() {
+            LOGGER.trace("overall processed={}", processed);
+            if( discarded > 0 ) {
+                LOGGER.warn("overall discarded={}",discarded);
+            }
+            router.removeEventListener(observed, this);
+        }
+
+        @Override
+        public void reset() {
+            events.clear();
+        }
+
+        @Override
+        public void handleEvent(EE event) {
+            processed++;
+            while( !events.offer(event) ) { 
+                Event ignored = events.poll();
+                discarded++;
+                if( 0 == (processed % LOG_BATCH) ) {
+                    LOGGER.warn("events flood. processed={} discarded={} event={}", processed, discarded, ignored);
+                }
+            }
+        }
+
+        @Override
+        public int discarded() {
+            return discarded;
+        }
+
+        @Override
+        public int counter() {
+            return processed;
+        }
+
+        @Override
+        public int pending() {
+            return events.size();
+        }
+
+    }
+    
+    private static class SingleLock<EE extends Event> extends QueEventLock<EE> {
+
+        public <T extends EE> SingleLock(Class<T> event, EventRouter router, int capacity) {
+            super(event, router, capacity);
+        }
+        
+        @Override
+        public EE waitForEvent() throws InterruptedException {
+            try {
+                return super.waitForEvent();
+            } finally {
+                release();
+            }
+        }
+
+        @Override
+        public <T extends EE> T waitForEvent(Class<T> event) throws InterruptedException {
+            try {
+                return super.waitForEvent(event);
+            } finally {
+                release();
+            }
+        }
+
+        @Override
+        public <T extends EE> T waitForEvent(Class<T> event, long timeout) throws InterruptedException {
+            try {
+                return super.waitForEvent(event, timeout);
+            } finally {
+                release();
+            }
+        }
+
+        @Override
+        public EE waitForEvent(long timeout) throws InterruptedException {
+            try {
+                return super.waitForEvent(timeout);
+            } finally {
+                release();
+            }
+        }
+        
+        
+        
+    }
+
+}

+ 0 - 1
assira/src/test/java/net/ranides/assira/collection/lists/IntRTListTest.java

@@ -23,7 +23,6 @@ public class IntRTListTest {
     @Test
     public void testSuite() {
         CollectionSuite.SUITE
-			.debug(true)
 			.param("collection!", $var)
 			.run((array) -> new IntRTList($var.list(array).valuesInt()));
 		

+ 3 - 3
assira/src/test/java/net/ranides/assira/collection/lists/RTListTest.java

@@ -30,9 +30,9 @@ public class RTListTest {
 	
 	@Test
     public void testConstruct() {
-        assertNotNull(new RTList());
-        assertNotNull(new RTList(new Integer[]{1,2,3}));
-        assertNotNull(new RTList(new Integer[]{}));
+        assertNotNull(new RTList<>());
+        assertNotNull(new RTList<>(new Integer[]{1,2,3}));
+        assertNotNull(new RTList<>(new Integer[]{}));
     }
 	
 }