tmf: Use same field format in properties and events views
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / signal / TmfSignalManager.java
CommitLineData
8c8bf09f 1/*******************************************************************************
61759503 2 * Copyright (c) 2009, 2012 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
8d2e2848
FC
35 // The set of event listeners and their corresponding handler methods.
36 // Note: listeners could be restricted to ITmfComponents but there is no
e31e01e8
FC
37 // harm in letting anyone use this since it is not tied to anything but
38 // the signal data type.
8c8bf09f 39 static private Map<Object, Method[]> fListeners = new HashMap<Object, Method[]>();
d5c13688 40 static private Map<Object, Method[]> fVIPListeners = new HashMap<Object, Method[]>();
8c8bf09f 41
8d2e2848 42 // If requested, add universal signal tracer
6256d8ad 43 // TODO: Temporary solution: should be enabled/disabled dynamically
8f965dd5 44 private static boolean fTraceIsActive = false;
8d2e2848 45 private static TmfSignalTracer fSignalTracer;
82b08e62
FC
46 static {
47 if (fTraceIsActive) {
8d2e2848 48 fSignalTracer = TmfSignalTracer.getInstance();
e31e01e8 49 register(fSignalTracer);
82b08e62
FC
50 }
51 }
8c8bf09f 52
4f8ca6a1
AM
53 /**
54 * Register an object to the signal manager. This object can then implement
55 * handler methods, marked with @TmfSignalHandler and with the expected
56 * signal type as parameter.
57 *
58 * @param listener
59 * The object that will be notified of new signals
60 */
61 public static synchronized void register(Object listener) {
62 Method[] methods = getSignalHandlerMethods(listener);
63 if (methods.length > 0) {
64 fListeners.put(listener, methods);
65 }
66 }
8c8bf09f 67
4f8ca6a1
AM
68 /**
69 * Register an object to the signal manager as a "VIP" listener. All VIP
70 * listeners will all receive the signal before the manager moves on to the
71 * lowly, non-VIP listeners.
72 *
73 * @param listener
74 * The object that will be notified of new signals
75 */
d5c13688
FC
76 public static synchronized void registerVIP(Object listener) {
77 Method[] methods = getSignalHandlerMethods(listener);
6256d8ad 78 if (methods.length > 0) {
d5c13688 79 fVIPListeners.put(listener, methods);
6256d8ad 80 }
d5c13688
FC
81 }
82
4f8ca6a1
AM
83 /**
84 * De-register a listener object from the signal manager. This means that
85 * its @TmfSignalHandler methods will no longer be called.
86 *
87 * @param listener
88 * The object to de-register
89 */
90 public static synchronized void deregister(Object listener) {
91 fVIPListeners.remove(listener);
d5c13688 92 fListeners.remove(listener);
4f8ca6a1 93 }
8c8bf09f
ASL
94
95 /**
8d2e2848
FC
96 * Returns the list of signal handlers in the listener. Signal handler name
97 * is irrelevant; only the annotation (@TmfSignalHandler) is important.
6256d8ad 98 *
8d2e2848
FC
99 * @param listener
100 * @return
101 */
102 static private Method[] getSignalHandlerMethods(Object listener) {
103 List<Method> handlers = new ArrayList<Method>();
104 Method[] methods = listener.getClass().getMethods();
105 for (Method method : methods) {
106 if (method.isAnnotationPresent(TmfSignalHandler.class)) {
107 handlers.add(method);
108 }
109 }
110 return handlers.toArray(new Method[handlers.size()]);
111 }
112
063f0d27
AM
113 static int fSignalId = 0;
114
8d2e2848
FC
115 /**
116 * Invokes the handling methods that listens to signals of a given type.
6256d8ad 117 *
8c8bf09f
ASL
118 * The list of handlers is built on-the-fly to allow for the dynamic
119 * creation/deletion of signal handlers. Since the number of signal
120 * handlers shouldn't be too high, this is not a big performance issue
121 * to pay for the flexibility.
6256d8ad 122 *
fc6ccf6f 123 * For synchronization purposes, the signal is bracketed by two synch signals.
6256d8ad 124 *
fc6ccf6f 125 * @param signal the signal to dispatch
8c8bf09f 126 */
8d2e2848 127 static public synchronized void dispatchSignal(TmfSignal signal) {
1b70b6dc
PT
128 int signalId = fSignalId++;
129 sendSignal(new TmfStartSynchSignal(signalId));
130 signal.setReference(signalId);
fc6ccf6f 131 sendSignal(signal);
1b70b6dc 132 sendSignal(new TmfEndSynchSignal(signalId));
fc6ccf6f
FC
133 }
134
d5c13688
FC
135 static private void sendSignal(TmfSignal signal) {
136 sendSignal(fVIPListeners, signal);
137 sendSignal(fListeners, signal);
138 }
139
140 static private void sendSignal(Map<Object, Method[]> listeners, TmfSignal signal) {
141
5500a7f0
FC
142 if (TmfCoreTracer.isSignalTraced()) {
143 TmfCoreTracer.traceSignal(signal, "(start)"); //$NON-NLS-1$
6256d8ad 144 }
d5c13688
FC
145
146 // Build the list of listener methods that are registered for this signal
147 Class<?> signalClass = signal.getClass();
148 Map<Object, List<Method>> targets = new HashMap<Object, List<Method>>();
149 targets.clear();
150 for (Map.Entry<Object, Method[]> entry : listeners.entrySet()) {
151 List<Method> matchingMethods = new ArrayList<Method>();
152 for (Method method : entry.getValue()) {
153 if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) {
154 matchingMethods.add(method);
155 }
156 }
157 if (!matchingMethods.isEmpty()) {
158 targets.put(entry.getKey(), matchingMethods);
159 }
160 }
161
6256d8ad 162 // Call the signal handlers
d5c13688
FC
163 for (Map.Entry<Object, List<Method>> entry : targets.entrySet()) {
164 for (Method method : entry.getValue()) {
165 try {
166 method.invoke(entry.getKey(), new Object[] { signal });
5500a7f0 167 if (TmfCoreTracer.isSignalTraced()) {
d5c13688
FC
168 Object key = entry.getKey();
169 String hash = String.format("%1$08X", entry.getKey().hashCode()); //$NON-NLS-1$
170 String target = "[" + hash + "] " + key.getClass().getSimpleName() + ":" + method.getName(); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
5500a7f0 171 TmfCoreTracer.traceSignal(signal, target);
d5c13688
FC
172 }
173 } catch (IllegalArgumentException e) {
5500a7f0 174 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688 175 } catch (IllegalAccessException e) {
5500a7f0 176 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688 177 } catch (InvocationTargetException e) {
5500a7f0 178 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688
FC
179 }
180 }
181 }
182
5500a7f0
FC
183 if (TmfCoreTracer.isSignalTraced()) {
184 TmfCoreTracer.traceSignal(signal, "(end)"); //$NON-NLS-1$
6256d8ad 185 }
d5c13688 186 }
dc299841 187
dc299841 188}
This page took 0.051409 seconds and 5 git commands to generate.