Ranides Atterwim 3 år sedan
förälder
incheckning
c49cba52fc

+ 4 - 2
assira.core/src/main/java/net/ranides/assira/events/EventObserver.java

@@ -6,6 +6,8 @@
  */
 package net.ranides.assira.events;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import net.ranides.assira.concurrent.SwingInvoker;
@@ -40,7 +42,7 @@ public class EventObserver implements EventListener<Event> {
         listeners = IClass.typefor(delegator)
             .methods()
             .require(EventHandler.class)
-            .require(IAttribute.VOID)
+            .require(IClass.VOID)
             .matches(EVENT)
             .list(m -> newListener(delegator, m));
     }
@@ -79,7 +81,7 @@ public class EventObserver implements EventListener<Event> {
             default:
                 return new NHandler(router, type, m.bind(delegator));
         }
-        
+
     }
 
     @Override

+ 2 - 2
assira.core/src/main/java/net/ranides/assira/reflection/impl/AElements.java

@@ -78,12 +78,12 @@ public abstract class AElements<T> implements IElements<T> {
     
     @Override
     public final <R> List<R> list(Function<? super T, R> mapper) {
-        return cquery.map(mapper).list();
+        return cquery.map(mapper).fetch().list();
     }
     
     @Override
     public final List<T> list() {
-        return cquery.list();
+        return cquery.fetch().list();
     }
     
     @Override

+ 53 - 10
assira.core/src/main/java/net/ranides/assira/time/TimeMetric.java

@@ -11,6 +11,8 @@ import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
 import net.ranides.assira.collection.maps.IdentMap;
 
 /**
@@ -31,12 +33,14 @@ public final class TimeMetric {
     
     private final Deque<Long> stack = new ArrayDeque<>();
 
+    private final boolean threadsafe;
+
     /**
      * Creates new inactive stopwatch.
      * Returned results are expressed in milliseconds by default.
      */
     public TimeMetric() {
-        this(TimeUnit.MILLISECONDS);
+        this(false);
     }
 
     /**
@@ -49,7 +53,29 @@ public final class TimeMetric {
      * @param unit unit
      */
     public TimeMetric(TimeUnit unit) {
+        this(false, unit);
+    }
+
+    /**
+     * Creates new inactive stopwatch.
+     * Returned results are expressed in milliseconds by default.
+     */
+    public TimeMetric(boolean threadsafe) {
+        this(threadsafe, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Creates new inactive stopwatch.
+     * Returned results are expressed in "unit" by default.
+     *
+     * Please note, that "unit" does not internal precision, but only default results returned
+     * by split or stop
+     *
+     * @param unit unit
+     */
+    public TimeMetric(boolean threadsafe, TimeUnit unit) {
         this.unit = unit;
+        this.threadsafe = threadsafe;
         start();
     }
 
@@ -60,8 +86,10 @@ public final class TimeMetric {
      * @return this
      */
     public TimeMetric start() {
-        stack.push(System.nanoTime());
-        return this;
+        return $synchronized(() -> {
+            stack.push(System.nanoTime());
+            return this;
+        });
     }
 
     /**
@@ -82,7 +110,9 @@ public final class TimeMetric {
      * @return elapsed time
      */
     public long stop(TimeUnit unit) {
-        return time(unit, stack.pop());
+        return $synchronized(() -> {
+            return time(unit, stack.pop());
+        });
     }
 
     /**
@@ -115,14 +145,27 @@ public final class TimeMetric {
      * @return elapsed time
      */
     public long time(TimeUnit unit) {
-        if(stack.isEmpty()) {
-            throw new IllegalStateException("#start must be called first");
+        return $synchronized(() -> {
+            if (stack.isEmpty()) {
+                throw new IllegalStateException("#start must be called first");
+            }
+            return time(unit, stack.peek());
+        });
+    }
+
+    private <T> T $synchronized(Supplier<T> action) {
+        if(threadsafe) {
+            synchronized (stack) {
+                return action.get();
+            }
+        } else {
+            return action.get();
         }
-        return time(unit, stack.peek());
     }
-    
-    private long time(TimeUnit unit, long dt) {
-        return unit.convert(System.nanoTime() -  dt, TimeUnit.NANOSECONDS);
+
+
+    private static long time(TimeUnit unit, long dt) {
+        return unit.convert(System.nanoTime() - dt, TimeUnit.NANOSECONDS);
     }
 
     @Override

+ 24 - 0
assira.core/src/test/java/net/ranides/assira/concurrent/TaskInvokerTest.java

@@ -1,5 +1,6 @@
 package net.ranides.assira.concurrent;
 
+import net.ranides.assira.functional.special.CancelableConsumer;
 import net.ranides.assira.functional.special.CancelableRunnable;
 import net.ranides.assira.junit.ManualTestUtils;
 import org.junit.Ignore;
@@ -56,4 +57,27 @@ public class TaskInvokerTest {
 
         System.out.println( "t=" + (System.currentTimeMillis()-ts) + " end");
     }
+
+    @Test
+    public void lazyConsumer() {
+        final long ts = System.currentTimeMillis();
+
+        CancelableConsumer<Object> lazy = TaskInvoker.lazy(500, (v) -> {
+            System.out.println("t=" + (System.currentTimeMillis()-ts) + " executed" );
+        });
+
+        System.out.println( "t=" + (System.currentTimeMillis()-ts));
+        lazy.accept("1");
+        ManualTestUtils.sleep(1000);
+
+        System.out.println( "t=" + (System.currentTimeMillis()-ts));
+        lazy.accept("2");
+        ManualTestUtils.sleep(1000);
+
+        System.out.println( "t=" + (System.currentTimeMillis()-ts));
+        lazy.accept("3");
+        ManualTestUtils.sleep(1000);
+
+        System.out.println( "t=" + (System.currentTimeMillis()-ts) + " end");
+    }
 }

+ 71 - 0
assira.core/src/test/java/net/ranides/assira/events/EventObserverTest.java

@@ -0,0 +1,71 @@
+package net.ranides.assira.events;
+
+import lombok.Data;
+import net.ranides.assira.junit.ManualTestUtils;
+import net.ranides.assira.time.TimeMetric;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("manual")
+public class EventObserverTest {
+
+    /**
+     * Expected something like:
+     *
+     * NOW   100 first
+     * NOW   100 second
+     * NOW   200 third
+     *
+     * LAZY  400 third
+     * NOW   600 fourth
+     *
+     * LAZY  800 fourth
+     * LATER 1100 first
+     * LATER 1100 second
+     * LATER 1200 third
+     * LATER 1600 fourth
+     *
+     */
+    @Test
+    public void lazy() {
+        TimeMetric tm = new TimeMetric(false);
+
+        EventObserver observer = EventObserver.newInstance(new Object() {
+            @EventHandler()
+            public void now(Event event) {
+                System.out.printf("NOW   %d %s%n", tm.time(), event);
+            }
+
+            @EventHandler(router = EventHandler.LATER, delay = 1000)
+            public void later(Event event) {
+                System.out.printf("LATER %d %s%n", tm.time(), event);
+            }
+
+            @EventHandler(router = EventHandler.LAZY, delay = 200)
+            public void lazy(Event event) {
+                System.out.printf("%nLAZY  %d %s%n", tm.time(), event);
+            }
+        });
+
+        System.out.println("creation2: " + tm.time());
+
+        observer.handleEvent(new MyEvent("first"));
+        observer.handleEvent(new MyEvent("second"));
+        ManualTestUtils.sleep(100);
+        observer.handleEvent(new MyEvent("third"));
+        ManualTestUtils.sleep(400);
+        observer.handleEvent(new MyEvent("fourth"));
+
+        ManualTestUtils.sleep(3000);
+    }
+
+    @Data
+    public static class MyEvent implements Event {
+        private final String tag;
+
+        @Override
+        public String toString() {
+            return tag;
+        }
+    }
+}