tmf/lttng: Remove unneeded (non-Javadoc) comments
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / signal / TmfSignalManager.java
CommitLineData
8c8bf09f 1/*******************************************************************************
11252342 2 * Copyright (c) 2009, 2013 Ericsson
6256d8ad 3 *
8c8bf09f
ASL
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
6256d8ad 8 *
8c8bf09f
ASL
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
6c13869b 13package org.eclipse.linuxtools.tmf.core.signal;
8c8bf09f
ASL
14
15import java.lang.reflect.InvocationTargetException;
16import java.lang.reflect.Method;
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21
8555a0f3 22import org.eclipse.linuxtools.internal.tmf.core.Activator;
5500a7f0 23import org.eclipse.linuxtools.internal.tmf.core.TmfCoreTracer;
dc299841 24
8c8bf09f 25/**
8d2e2848
FC
26 * This class manages the set of signal listeners and the signals they are
27 * interested in. When a signal is broadcasted, the appropriate listeners
28 * signal handlers are invoked.
6256d8ad 29 *
4b7b3670
FC
30 * @version 1.0
31 * @author Francois Chouinard
4f8ca6a1 32 */
8c8bf09f
ASL
33public class TmfSignalManager {
34
d9ec9800
AM
35 // The set of event listeners and their corresponding handler methods.
36 // Note: listeners could be restricted to ITmfComponents but there is no
37 // harm in letting anyone use this since it is not tied to anything but
38 // the signal data type.
39 private static Map<Object, Method[]> fListeners = new HashMap<Object, Method[]>();
40 private static Map<Object, Method[]> fVIPListeners = new HashMap<Object, Method[]>();
41
42 // If requested, add universal signal tracer
43 // TODO: Temporary solution: should be enabled/disabled dynamically
44 private static boolean fTraceIsActive = false;
45 private static TmfSignalTracer fSignalTracer;
46
47 static {
48 if (fTraceIsActive) {
49 fSignalTracer = TmfSignalTracer.getInstance();
50 register(fSignalTracer);
51 }
52 }
8c8bf09f 53
4f8ca6a1
AM
54 /**
55 * Register an object to the signal manager. This object can then implement
56 * handler methods, marked with @TmfSignalHandler and with the expected
57 * signal type as parameter.
58 *
59 * @param listener
60 * The object that will be notified of new signals
61 */
62 public static synchronized void register(Object listener) {
63 Method[] methods = getSignalHandlerMethods(listener);
64 if (methods.length > 0) {
65 fListeners.put(listener, methods);
66 }
67 }
8c8bf09f 68
4f8ca6a1
AM
69 /**
70 * Register an object to the signal manager as a "VIP" listener. All VIP
71 * listeners will all receive the signal before the manager moves on to the
72 * lowly, non-VIP listeners.
73 *
74 * @param listener
75 * The object that will be notified of new signals
76 */
d5c13688
FC
77 public static synchronized void registerVIP(Object listener) {
78 Method[] methods = getSignalHandlerMethods(listener);
6256d8ad 79 if (methods.length > 0) {
d5c13688 80 fVIPListeners.put(listener, methods);
6256d8ad 81 }
d5c13688
FC
82 }
83
4f8ca6a1
AM
84 /**
85 * De-register a listener object from the signal manager. This means that
86 * its @TmfSignalHandler methods will no longer be called.
87 *
88 * @param listener
89 * The object to de-register
90 */
91 public static synchronized void deregister(Object listener) {
92 fVIPListeners.remove(listener);
d5c13688 93 fListeners.remove(listener);
4f8ca6a1 94 }
8c8bf09f 95
d9ec9800
AM
96 /**
97 * Returns the list of signal handlers in the listener. Signal handler name
98 * is irrelevant; only the annotation (@TmfSignalHandler) is important.
99 *
100 * @param listener
101 * @return
102 */
103 private static Method[] getSignalHandlerMethods(Object listener) {
104 List<Method> handlers = new ArrayList<Method>();
105 Method[] methods = listener.getClass().getMethods();
106 for (Method method : methods) {
107 if (method.isAnnotationPresent(TmfSignalHandler.class)) {
108 handlers.add(method);
109 }
110 }
111 return handlers.toArray(new Method[handlers.size()]);
112 }
113
114 static int fSignalId = 0;
115
116 /**
117 * Invokes the handling methods that listens to signals of a given type.
118 *
119 * The list of handlers is built on-the-fly to allow for the dynamic
120 * creation/deletion of signal handlers. Since the number of signal handlers
121 * shouldn't be too high, this is not a big performance issue to pay for the
122 * flexibility.
123 *
124 * For synchronization purposes, the signal is bracketed by two synch
125 * signals.
126 *
127 * @param signal
128 * the signal to dispatch
129 */
130 public static synchronized void dispatchSignal(TmfSignal signal) {
131 int signalId = fSignalId++;
132 sendSignal(new TmfStartSynchSignal(signalId));
133 signal.setReference(signalId);
134 sendSignal(signal);
135 sendSignal(new TmfEndSynchSignal(signalId));
136 }
137
138 private static void sendSignal(TmfSignal signal) {
d5c13688
FC
139 sendSignal(fVIPListeners, signal);
140 sendSignal(fListeners, signal);
141 }
142
d9ec9800 143 private static void sendSignal(Map<Object, Method[]> listeners, TmfSignal signal) {
d5c13688 144
5500a7f0
FC
145 if (TmfCoreTracer.isSignalTraced()) {
146 TmfCoreTracer.traceSignal(signal, "(start)"); //$NON-NLS-1$
6256d8ad 147 }
d5c13688
FC
148
149 // Build the list of listener methods that are registered for this signal
150 Class<?> signalClass = signal.getClass();
151 Map<Object, List<Method>> targets = new HashMap<Object, List<Method>>();
152 targets.clear();
153 for (Map.Entry<Object, Method[]> entry : listeners.entrySet()) {
154 List<Method> matchingMethods = new ArrayList<Method>();
155 for (Method method : entry.getValue()) {
156 if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) {
157 matchingMethods.add(method);
158 }
159 }
160 if (!matchingMethods.isEmpty()) {
161 targets.put(entry.getKey(), matchingMethods);
162 }
163 }
164
6256d8ad 165 // Call the signal handlers
d5c13688
FC
166 for (Map.Entry<Object, List<Method>> entry : targets.entrySet()) {
167 for (Method method : entry.getValue()) {
168 try {
169 method.invoke(entry.getKey(), new Object[] { signal });
5500a7f0 170 if (TmfCoreTracer.isSignalTraced()) {
d5c13688
FC
171 Object key = entry.getKey();
172 String hash = String.format("%1$08X", entry.getKey().hashCode()); //$NON-NLS-1$
173 String target = "[" + hash + "] " + key.getClass().getSimpleName() + ":" + method.getName(); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
5500a7f0 174 TmfCoreTracer.traceSignal(signal, target);
d5c13688
FC
175 }
176 } catch (IllegalArgumentException e) {
5500a7f0 177 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688 178 } catch (IllegalAccessException e) {
5500a7f0 179 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688 180 } catch (InvocationTargetException e) {
5500a7f0 181 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688
FC
182 }
183 }
184 }
185
5500a7f0
FC
186 if (TmfCoreTracer.isSignalTraced()) {
187 TmfCoreTracer.traceSignal(signal, "(end)"); //$NON-NLS-1$
6256d8ad 188 }
d5c13688 189 }
dc299841 190
dc299841 191}
This page took 0.067752 seconds and 5 git commands to generate.