You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2012/03/02 22:16:46 UTC

svn commit: r1296479 - /commons/sandbox/graph/trunk/src/main/java/org/apache/commons/graph/CommonsGraph.java

Author: simonetripodi
Date: Fri Mar  2 21:16:46 2012
New Revision: 1296479

URL: http://svn.apache.org/viewvc?rev=1296479&view=rev
Log:
[SANDBOX-400] first implementation of methods to synchronize existing Graph data structures to make them thread-safe

Modified:
    commons/sandbox/graph/trunk/src/main/java/org/apache/commons/graph/CommonsGraph.java

Modified: commons/sandbox/graph/trunk/src/main/java/org/apache/commons/graph/CommonsGraph.java
URL: http://svn.apache.org/viewvc/commons/sandbox/graph/trunk/src/main/java/org/apache/commons/graph/CommonsGraph.java?rev=1296479&r1=1296478&r2=1296479&view=diff
==============================================================================
--- commons/sandbox/graph/trunk/src/main/java/org/apache/commons/graph/CommonsGraph.java (original)
+++ commons/sandbox/graph/trunk/src/main/java/org/apache/commons/graph/CommonsGraph.java Fri Mar  2 21:16:46 2012
@@ -19,8 +19,14 @@ package org.apache.commons.graph;
  * under the License.
  */
 
+import static java.lang.reflect.Proxy.newProxyInstance;
 import static org.apache.commons.graph.utils.Assertions.checkNotNull;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.apache.commons.graph.builder.DefaultLinkedConnectionBuilder;
 import org.apache.commons.graph.builder.GraphConnection;
 import org.apache.commons.graph.builder.LinkedConnectionBuilder;
@@ -210,6 +216,105 @@ public final class CommonsGraph<V extend
     }
 
     /**
+     * Returns a synchronized (thread-safe) {@link Graph} backed by the specified Graph.
+     *
+     * @param graph
+     * @return
+     */
+    public static <V extends Vertex, E extends Edge> Graph<V, E> synchronize( Graph<V, E> graph )
+    {
+        return synchronizedObject( graph, Graph.class );
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) {@link DirectedGraph} backed by the specified Graph.
+     *
+     * @param graph
+     * @return
+     */
+    public static <V extends Vertex, E extends Edge> Graph<V, E> synchronize( DirectedGraph<V, E> graph )
+    {
+        return synchronizedObject( graph, DirectedGraph.class );
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) {@link UndirectedGraph} backed by the specified Graph.
+     *
+     * @param graph
+     * @return
+     */
+    public static <V extends Vertex, E extends Edge> Graph<V, E> synchronize( UndirectedGraph<V, E> graph )
+    {
+        return synchronizedObject( graph, UndirectedGraph.class );
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) {@link MutableGraph} backed by the specified Graph.
+     *
+     * @param graph
+     * @return
+     */
+    public static <V extends Vertex, E extends Edge> Graph<V, E> synchronize( MutableGraph<V, E> graph )
+    {
+        return synchronizedObject( graph, MutableGraph.class );
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) {@link WeightedGraph} backed by the specified Graph.
+     *
+     * @param graph
+     * @return
+     */
+    public static <V extends Vertex, WE extends WeightedEdge<W>, W> Graph<V, WE> synchronize( WeightedGraph<V, WE, W> graph )
+    {
+        return synchronizedObject( graph, WeightedGraph.class );
+    }
+
+   /**
+    * Wrap the given object in a proxed one where all methods declared in the given interface will be synchronized.
+    *
+    * @param <T> the object type has to be proxed
+    * @param toBeSynchronized to object which methods have to be synchronized
+    * @param type the interface has to be proxed
+    * @return the dynamic synchronized proxy
+    */
+    private static <T> T synchronizedObject( T toBeSynchronized, final Class<T> type )
+    {
+        final T checkedToBeSynchronized = checkNotNull( toBeSynchronized, "Impossible to synchronize a null graph!" );
+
+        /*
+         * Used to synchronize method declared on the pool/factory interface only.
+         */
+        final Set<Method> synchronizedMethods = new HashSet<Method>();
+
+        for ( Method method : type.getDeclaredMethods() )
+        {
+            synchronizedMethods.add( method );
+        }
+
+        return type.cast( newProxyInstance( type.getClassLoader(), new Class<?>[] { type },
+                          new InvocationHandler()
+                          {
+
+                              private final Object lock = new Object();
+
+                              public Object invoke( Object proxy, Method method, Object[] args )
+                                  throws Throwable
+                              {
+                                  if ( synchronizedMethods.contains( method ) )
+                                  {
+                                      synchronized ( this.lock )
+                                      {
+                                          return method.invoke( checkedToBeSynchronized, args );
+                                      }
+                                  }
+                                  return method.invoke( checkedToBeSynchronized, args );
+                              }
+
+                          } ) );
+    }
+
+    /**
      * Hidden constructor, this class cannot be instantiated.
      */
     private CommonsGraph()