Rename xxx.lttng to xxx.lttng.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / signal / TmfSignalManager.java
index 63759041e0faa0cd790e6753a90584739ead9d4a..45a54a79021d98f87f0758cf06baa07914d433a4 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009 Ericsson
+ * Copyright (c) 2009, 2010 Ericsson
  * 
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
@@ -19,129 +19,51 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.linuxtools.tmf.Tracer;
+
 /**
  * <b><u>TmfSignalHandler</u></b>
  * <p>
- * TODO: Implement me. Please.
+ * This class manages the set of signal listeners and the signals they are
+ * interested in. When a signal is broadcasted, the appropriate listeners
+ * signal handlers are invoked.
  * <p>
- * TODO: Error/exception handling
  */
 public class TmfSignalManager {
 
-       /**
-        * The set of event listeners and their corresponding handler methods.
-        */
+       // The set of event listeners and their corresponding handler methods.
+       // Note: listeners could be restricted to ITmfComponents but there is no
+       // harm in letting anyone use this since it is not tied to anything but
+       // the signal data type.
        static private Map<Object, Method[]> fListeners = new HashMap<Object, Method[]>();
+    static private Map<Object, Method[]> fVIPListeners = new HashMap<Object, Method[]>();
 
-       // TODO: read from the preferences
+       // If requested, add universal signal tracer
+       // TODO: Temporary solution: should be enabled/disabled dynamically 
        private static boolean fTraceIsActive = false;
-       private static TmfSignalTrace fSignalTracer;
-
-//     private static TmfSignalManager fInstance;
-
+       private static TmfSignalTracer fSignalTracer;
        static {
                if (fTraceIsActive) {
-                       fSignalTracer = new TmfSignalTrace();
-                       addListener(fSignalTracer);
+                       fSignalTracer = TmfSignalTracer.getInstance();
+                       register(fSignalTracer);
                }
        }
 
-       public static synchronized void addListener(Object listener) {
+       public static synchronized void register(Object listener) {
                Method[] methods = getSignalHandlerMethods(listener);
                if (methods.length > 0)
                        fListeners.put(listener, methods);
        }
 
-       public static synchronized void removeListener(Object listener) {
-               fListeners.remove(listener);
-       }
-
-//     public static TmfSignalManager getInstance() {
-//             if (fInstance == null) {
-//                     fInstance = new TmfSignalManager();
-//             }
-//             return fInstance;
-//     }
-
-       /**
-        * Invokes the handling methods that expect this signal.
-        * 
-        * The list of handlers is built on-the-fly to allow for the dynamic
-        * creation/deletion of signal handlers. Since the number of signal
-        * handlers shouldn't be too high, this is not a big performance issue
-        * to pay for the flexibility.
-        * 
-        * @param signal
-        */
-//     private class Dispatch implements Runnable {
-//
-//             private final Method method;
-//             private final Object entry;
-//             private final Object signal;
-//
-//             public Dispatch(Method m, Object e, Object s) {
-//                     method = m;
-//                     entry = e;
-//                     signal = s;
-//             }
-//
-//             public void run() {
-//                     try {
-//                             method.invoke(entry, new Object[] { signal });
-//                     } catch (IllegalArgumentException e) {
-//                             // TODO Auto-generated catch block
-//                             e.printStackTrace();
-//                     } catch (IllegalAccessException e) {
-//                             // TODO Auto-generated catch block
-//                             e.printStackTrace();
-//                     } catch (InvocationTargetException e) {
-//                             // TODO Auto-generated catch block
-//                             e.printStackTrace();
-//                     }
-//             }
-//     }
-//     
-//     private void dispatch(Method method, Object key, Object signal) {
-//             Dispatch disp = new Dispatch(method, key, signal);
-//             new Thread(disp).start();
-//     }
-
-       static public synchronized void dispatchSignal(Object signal) {
-
-               // Build the list of listener methods that are registered for this signal
-               Class<?> signalClass = signal.getClass();
-               Map<Object, List<Method>> listeners = new HashMap<Object, List<Method>>();
-               listeners.clear();
-               for (Map.Entry<Object, Method[]> entry : fListeners.entrySet()) {
-                       List<Method> matchingMethods = new ArrayList<Method>();
-                       for (Method method : entry.getValue()) {
-                               if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) {
-                                       matchingMethods.add(method);
-                               }
-                       }
-                       if (!matchingMethods.isEmpty()) {
-                               listeners.put(entry.getKey(), matchingMethods);
-                       }
-               }
+    public static synchronized void registerVIP(Object listener) {
+        Method[] methods = getSignalHandlerMethods(listener);
+        if (methods.length > 0)
+            fVIPListeners.put(listener, methods);
+    }
 
-               // Call the signal handlers
-               for (Map.Entry<Object, List<Method>> entry : listeners.entrySet()) {
-                       for (Method method : entry.getValue()) {
-//                             getInstance().dispatch(method, entry.getKey(), signal);
-                               try {
-                                       method.invoke(entry.getKey(), new Object[] { signal });
-                               } catch (IllegalArgumentException e) {
-                                       // TODO Auto-generated catch block
-                                       e.printStackTrace();
-                               } catch (IllegalAccessException e) {
-                                       // TODO Auto-generated catch block
-                                       e.printStackTrace();
-                               } catch (InvocationTargetException e) {
-                                       // TODO Auto-generated catch block
-                                       e.printStackTrace();
-                               }
-                       }
-               }
+       public static synchronized void deregister(Object listener) {
+               fVIPListeners.remove(listener);
+        fListeners.remove(listener);
        }
 
        /**
@@ -162,4 +84,71 @@ public class TmfSignalManager {
                return handlers.toArray(new Method[handlers.size()]);
        }
 
-}
\ No newline at end of file
+       /**
+        * Invokes the handling methods that listens to signals of a given type.
+        * 
+        * The list of handlers is built on-the-fly to allow for the dynamic
+        * creation/deletion of signal handlers. Since the number of signal
+        * handlers shouldn't be too high, this is not a big performance issue
+        * to pay for the flexibility.
+        * 
+        * For synchronization purposes, the signal is bracketed by two synch signals.
+        * 
+        * @param signal the signal to dispatch
+        */
+       static int fSignalId = 0;
+       static public synchronized void dispatchSignal(TmfSignal signal) {
+               fSignalId++;
+               sendSignal(new TmfStartSynchSignal(fSignalId));
+               signal.setReference(fSignalId);
+               sendSignal(signal);
+               sendSignal(new TmfEndSynchSignal(fSignalId));
+       }
+
+    static private void sendSignal(TmfSignal signal) {
+        sendSignal(fVIPListeners, signal);
+        sendSignal(fListeners, signal);
+    }
+
+    static private void sendSignal(Map<Object, Method[]> listeners, TmfSignal signal) {
+
+        if (Tracer.isSignalTraced()) Tracer.traceSignal(signal, "(start)"); //$NON-NLS-1$
+
+        // Build the list of listener methods that are registered for this signal
+        Class<?> signalClass = signal.getClass();
+        Map<Object, List<Method>> targets = new HashMap<Object, List<Method>>();
+        targets.clear();
+        for (Map.Entry<Object, Method[]> entry : listeners.entrySet()) {
+            List<Method> matchingMethods = new ArrayList<Method>();
+            for (Method method : entry.getValue()) {
+                if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) {
+                    matchingMethods.add(method);
+                }
+            }
+            if (!matchingMethods.isEmpty()) {
+                targets.put(entry.getKey(), matchingMethods);
+            }
+        }
+
+        // Call the signal handlers 
+        for (Map.Entry<Object, List<Method>> entry : targets.entrySet()) {
+            for (Method method : entry.getValue()) {
+                try {
+                    method.invoke(entry.getKey(), new Object[] { signal });
+                    if (Tracer.isSignalTraced()) {
+                        Object key = entry.getKey();
+                        String hash = String.format("%1$08X", entry.getKey().hashCode()); //$NON-NLS-1$
+                        String target = "[" + hash + "] " + key.getClass().getSimpleName() + ":" + method.getName();   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+                        Tracer.traceSignal(signal, target);                     
+                    }
+                } catch (IllegalArgumentException e) {
+                } catch (IllegalAccessException e) {
+                } catch (InvocationTargetException e) {
+                }
+            }
+        }
+
+        if (Tracer.isSignalTraced()) Tracer.traceSignal(signal, "(end)"); //$NON-NLS-1$
+    }
+
+}
This page took 0.026335 seconds and 5 git commands to generate.