Revision: 1074
Author: dhanji
Date: Sat Sep  5 23:22:08 2009
Log: Lifecycle now supports parallel execution. Need to add support for  
parallel startup and autostart next.

TODO added to check servlet spec compliance in GS2 request dispatcher.
http://code.google.com/p/google-guice/source/detail?r=1074

Added:
   
/trunk/lifecycle/test/com/google/inject/lifecycle/ParallelizedBroadcastTest.java
Modified:
  /trunk/lifecycle/src/com/google/inject/lifecycle/BroadcastingLifecycle.java
  /trunk/lifecycle/src/com/google/inject/lifecycle/Lifecycle.java
  /trunk/lifecycle/src/com/google/inject/lifecycle/ListOfMatchers.java
  /trunk/lifecycle/src/com/google/inject/lifecycle/Startable.java
   
/trunk/lifecycle/test/com/google/inject/lifecycle/ArbitraryBroadcastTest.java
   
/trunk/lifecycle/test/com/google/inject/lifecycle/MultipleStartableTest.java
  /trunk/lifecycle/test/com/google/inject/lifecycle/StartableTest.java
  /trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java

=======================================
--- /dev/null
+++  
/trunk/lifecycle/test/com/google/inject/lifecycle/ParallelizedBroadcastTest.java
         
Sat Sep  5 23:22:08 2009
@@ -0,0 +1,55 @@
+package com.google.inject.lifecycle;
+
+import com.google.inject.Guice;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import junit.framework.TestCase;
+
+/** @author [email protected] (Dhanji R. Prasanna) */
+public class ParallelizedBroadcastTest extends TestCase {
+  private static final AtomicInteger called = new AtomicInteger();
+
+  public final void testCallable() throws InterruptedException {
+    called.set(0);
+    Lifecycle lifecycle = Guice.createInjector(new LifecycleModule() {
+
+      @Override
+      protected void configureLifecycle() {
+        bind(Runnable.class).to(AClass.class);
+
+        // Does not get called because the key does not expose the  
callable.
+        bind(Object.class).to(AClass.class);
+
+        bind(BaseClass.class).to(AClass.class);
+
+        callable(Runnable.class);
+      }
+
+    }).getInstance(Lifecycle.class);
+
+    final ExecutorService executorService =  
Executors.newFixedThreadPool(3);
+    lifecycle
+      .broadcast(Runnable.class, executorService)
+      .run();
+
+    executorService.shutdown();
+    executorService.awaitTermination(5L, TimeUnit.SECONDS);
+
+    assertEquals(2, called.get());
+  }
+
+  public static class BaseClass implements Runnable {
+
+    public void run() {
+      called.incrementAndGet();
+    }
+  }
+
+  public static class AClass extends BaseClass implements Runnable {
+    public void run() {
+      super.run();
+    }
+  }
+}
=======================================
---  
/trunk/lifecycle/src/com/google/inject/lifecycle/BroadcastingLifecycle.java     
 
Fri Sep  4 02:08:15 2009
+++  
/trunk/lifecycle/src/com/google/inject/lifecycle/BroadcastingLifecycle.java     
 
Sat Sep  5 23:22:08 2009
@@ -14,11 +14,16 @@
  import java.lang.reflect.Method;
  import java.util.List;
  import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
  import net.sf.cglib.proxy.InvocationHandler;
  import net.sf.cglib.proxy.Proxy;

-/** @author [email protected] (Dhanji R. Prasanna) */
-...@singleton class BroadcastingLifecycle implements Lifecycle {
+/**
+ * @author [email protected] (Dhanji R. Prasanna)
+ */
+...@singleton
+class BroadcastingLifecycle implements Lifecycle {
    private final Injector injector;
    private final List<Class<?>> callableClasses;

@@ -103,6 +108,26 @@
    }

    public <T> T broadcast(Class<T> clazz, Matcher<? super T> matcher) {
+    final List<T> ts = instantiateForBroadcast(clazz, matcher);
+
+    @SuppressWarnings("unchecked") T caster = (T) Proxy
+        .newProxyInstance(clazz.getClassLoader(), new Class[] { clazz },  
new InvocationHandler() {
+          public Object invoke(Object o, Method method, Object[] objects)  
throws Throwable {
+
+            // propagate the method call with the same arg list to all  
instances.
+            for (T t : ts) {
+              method.invoke(t, objects);
+            }
+
+            // We can't return from multiple instances, so just return  
null.
+            return null;
+          }
+        });
+
+    return caster;
+  }
+
+  private <T> List<T> instantiateForBroadcast(Class<T> clazz, Matcher<?  
super T> matcher) {
      final List<T> ts = Lists.newArrayList();
      for (Key<?> key : callableKeys.get(clazz)) {
        // Should this get instancing happen during method call?
@@ -113,14 +138,31 @@
          ts.add(t);
        }
      }
+    return ts;
+  }
+
+  public <T> T broadcast(Class<T> clazz, final ExecutorService  
executorService) {
+    return broadcast(clazz, executorService, any());
+  }
+
+  public <T> T broadcast(Class<T> clazz, final ExecutorService  
executorService,
+      Matcher<? super T> matcher) {
+    final List<T> ts = instantiateForBroadcast(clazz, matcher);

      @SuppressWarnings("unchecked") T caster = (T) Proxy
          .newProxyInstance(clazz.getClassLoader(), new Class[] { clazz },  
new InvocationHandler() {
-          public Object invoke(Object o, Method method, Object[] objects)  
throws Throwable {
+          public Object invoke(Object o, final Method method, final  
Object[] objects)
+              throws Throwable {

              // propagate the method call with the same arg list to all  
instances.
-            for (T t : ts) {
-              method.invoke(t, objects);
+            for (final T t : ts) {
+              // Submit via executor service. TODO See if this can be  
parallelized by
+              // yet another dimension, i.e. inParallel(N)
+              executorService.submit(new Callable() {
+                public Object call() throws Exception {
+                  return method.invoke(t, objects);
+                }
+              });
              }

              // We can't return from multiple instances, so just return  
null.
=======================================
--- /trunk/lifecycle/src/com/google/inject/lifecycle/Lifecycle.java     Fri  
Sep  4 02:08:15 2009
+++ /trunk/lifecycle/src/com/google/inject/lifecycle/Lifecycle.java     Sat  
Sep  5 23:22:08 2009
@@ -2,9 +2,10 @@

  import com.google.inject.ImplementedBy;
  import com.google.inject.matcher.Matcher;
+import java.util.concurrent.ExecutorService;

  /**
- *  @author [email protected] (Dhanji R. Prasanna)
+ *  @author [email protected] (Dhanji R. Prasanna)
   */
  @ImplementedBy(BroadcastingLifecycle.class)
  public interface Lifecycle {
@@ -14,4 +15,8 @@
    <T> T broadcast(Class<T> clazz);

    <T> T broadcast(Class<T> clazz, Matcher<? super T> matcher);
-}
+
+  <T> T broadcast(Class<T> clazz, ExecutorService executorService);
+
+  <T> T broadcast(Class<T> clazz, ExecutorService executorService,  
Matcher<? super T> matcher);
+}
=======================================
--- /trunk/lifecycle/src/com/google/inject/lifecycle/ListOfMatchers.java        
 
Fri Sep  4 02:08:15 2009
+++ /trunk/lifecycle/src/com/google/inject/lifecycle/ListOfMatchers.java        
 
Sat Sep  5 23:22:08 2009
@@ -4,7 +4,7 @@
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;

-/** @author [email protected] (Dhanji R. Prasanna) */
+/** @author [email protected] (Dhanji R. Prasanna) */
  @Retention(RetentionPolicy.RUNTIME)
  @BindingAnnotation
  @interface ListOfMatchers {
=======================================
--- /trunk/lifecycle/src/com/google/inject/lifecycle/Startable.java     Fri  
Sep  4 02:08:15 2009
+++ /trunk/lifecycle/src/com/google/inject/lifecycle/Startable.java     Sat  
Sep  5 23:22:08 2009
@@ -10,7 +10,7 @@
   * All instances that wish to use startable *must* be bound as
   * singletons.
   *
- * @author [email protected] (Dhanji R. Prasanna)
+ * @author [email protected] (Dhanji R. Prasanna)
   */
  public interface Startable {
    /**
=======================================
---  
/trunk/lifecycle/test/com/google/inject/lifecycle/ArbitraryBroadcastTest.java   
 
Fri Sep  4 02:08:15 2009
+++  
/trunk/lifecycle/test/com/google/inject/lifecycle/ArbitraryBroadcastTest.java   
 
Sat Sep  5 23:22:08 2009
@@ -4,7 +4,7 @@
  import com.google.inject.Singleton;
  import junit.framework.TestCase;

-/** @author [email protected] (Dhanji R. Prasanna) */
+/** @author [email protected] (Dhanji R. Prasanna) */
  public class ArbitraryBroadcastTest extends TestCase {
    private static int called;

=======================================
---  
/trunk/lifecycle/test/com/google/inject/lifecycle/MultipleStartableTest.java    
 
Fri Sep  4 02:08:15 2009
+++  
/trunk/lifecycle/test/com/google/inject/lifecycle/MultipleStartableTest.java    
 
Sat Sep  5 23:22:08 2009
@@ -4,7 +4,7 @@
  import com.google.inject.Singleton;
  import junit.framework.TestCase;

-/** @author [email protected] (Dhanji R. Prasanna) */
+/** @author [email protected] (Dhanji R. Prasanna) */
  public class MultipleStartableTest extends TestCase {
    private static int started;

=======================================
--- /trunk/lifecycle/test/com/google/inject/lifecycle/StartableTest.java        
 
Fri Sep  4 02:08:15 2009
+++ /trunk/lifecycle/test/com/google/inject/lifecycle/StartableTest.java        
 
Sat Sep  5 23:22:08 2009
@@ -4,7 +4,7 @@
  import com.google.inject.Singleton;
  import junit.framework.TestCase;

-/** @author [email protected] (Dhanji R. Prasanna) */
+/** @author [email protected] (Dhanji R. Prasanna) */
  public class StartableTest extends TestCase {
    private static boolean started;

=======================================
---  
/trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java        
 
Tue Jun 16 11:47:41 2009
+++  
/trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java        
 
Sat Sep  5 23:22:08 2009
@@ -115,6 +115,10 @@
     */
    RequestDispatcher getRequestDispatcher(String path) {
      final String newRequestUri = path;
+
+    // TODO(dhanji): check servlet spec to see if the following is legal  
or not.
+    // Need to strip query string if requested...
+
      for (final ServletDefinition servletDefinition : servletDefinitions) {
        if (servletDefinition.shouldServe(path)) {
          return new RequestDispatcher() {

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to