• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #ifndef TraceEventDispatcher_h
32 #define TraceEventDispatcher_h
33 
34 #include "platform/TraceEvent.h"
35 #include "wtf/HashMap.h"
36 #include "wtf/Threading.h"
37 #include "wtf/ThreadingPrimitives.h"
38 #include "wtf/Vector.h"
39 #include "wtf/text/WTFString.h"
40 
41 namespace WebCore {
42 
43 class InspectorClient;
44 
45 struct TraceEventTargetBase {
~TraceEventTargetBaseTraceEventTargetBase46     virtual ~TraceEventTargetBase() { }
47 };
48 
49 template<typename C> struct TraceEventTarget;
50 
51 class TraceEventDispatcher {
52     WTF_MAKE_NONCOPYABLE(TraceEventDispatcher);
53 public:
54     class TraceEvent {
55     public:
TraceEvent()56         TraceEvent()
57             : m_name(0)
58             , m_argumentCount(0)
59         {
60         }
61 
TraceEvent(double timestamp,char phase,const char * name,unsigned long long id,ThreadIdentifier threadIdentifier,int argumentCount,const char * const * argumentNames,const unsigned char * argumentTypes,const unsigned long long * argumentValues)62         TraceEvent(double timestamp, char phase, const char* name, unsigned long long id, ThreadIdentifier threadIdentifier,
63             int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues)
64             : m_timestamp(timestamp)
65             , m_phase(phase)
66             , m_name(name)
67             , m_id(id)
68             , m_threadIdentifier(threadIdentifier)
69             , m_argumentCount(argumentCount)
70         {
71             if (m_argumentCount > MaxArguments) {
72                 ASSERT_NOT_REACHED();
73                 m_argumentCount = MaxArguments;
74             }
75             for (int i = 0; i < m_argumentCount; ++i) {
76                 m_argumentNames[i] = argumentNames[i];
77                 m_argumentTypes[i] = argumentTypes[i];
78                 m_argumentValues[i] = argumentValues[i];
79             }
80         }
81 
timestamp()82         double timestamp() const { return m_timestamp; }
phase()83         char phase() const { return m_phase; }
name()84         const char* name() const { return m_name; }
id()85         unsigned long long id() const { return m_id; }
threadIdentifier()86         ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; }
argumentCount()87         int argumentCount() const { return m_argumentCount; }
isNull()88         bool isNull() const { return !m_name; }
89 
asBool(const char * name)90         bool asBool(const char* name) const
91         {
92             return parameter(name, TRACE_VALUE_TYPE_BOOL).m_bool;
93         }
asInt(const char * name)94         long long asInt(const char* name) const
95         {
96             size_t index = findParameter(name);
97             if (index == kNotFound || (m_argumentTypes[index] != TRACE_VALUE_TYPE_INT && m_argumentTypes[index] != TRACE_VALUE_TYPE_UINT)) {
98                 ASSERT_NOT_REACHED();
99                 return 0;
100             }
101             return reinterpret_cast<const WebCore::TraceEvent::TraceValueUnion*>(m_argumentValues + index)->m_int;
102         }
asUInt(const char * name)103         unsigned long long asUInt(const char* name) const
104         {
105             return asInt(name);
106         }
asDouble(const char * name)107         double asDouble(const char* name) const
108         {
109             return parameter(name, TRACE_VALUE_TYPE_DOUBLE).m_double;
110         }
asString(const char * name)111         const char* asString(const char* name) const
112         {
113             return parameter(name, TRACE_VALUE_TYPE_STRING).m_string;
114         }
115 
116     private:
117         enum { MaxArguments = 2 };
118 
119         size_t findParameter(const char*) const;
120         const WebCore::TraceEvent::TraceValueUnion& parameter(const char* name, unsigned char expectedType) const;
121 
122         double m_timestamp;
123         char m_phase;
124         const char* m_name;
125         unsigned long long m_id;
126         ThreadIdentifier m_threadIdentifier;
127         int m_argumentCount;
128         const char* m_argumentNames[MaxArguments];
129         unsigned char m_argumentTypes[MaxArguments];
130         unsigned long long m_argumentValues[MaxArguments];
131     };
132 
133     typedef void (TraceEventTargetBase::*TraceEventHandlerMethod)(const TraceEvent&);
134 
instance()135     static TraceEventDispatcher* instance()
136     {
137         DEFINE_STATIC_LOCAL(TraceEventDispatcher, instance, ());
138         return &instance;
139     }
140 
141     template<typename ListenerClass>
addListener(const char * name,char phase,ListenerClass * instance,typename TraceEventTarget<ListenerClass>::TraceEventHandler handler,InspectorClient * client)142     void addListener(const char* name, char phase, ListenerClass* instance, typename TraceEventTarget<ListenerClass>::TraceEventHandler handler, InspectorClient* client)
143     {
144         innerAddListener(name, phase, instance, static_cast<TraceEventHandlerMethod>(handler), client);
145     }
146 
147     void removeAllListeners(TraceEventTargetBase*, InspectorClient*);
148     void processBackgroundEvents();
149 
150 private:
151     struct BoundTraceEventHandler {
152         TraceEventTargetBase* instance;
153         TraceEventHandlerMethod method;
154 
BoundTraceEventHandlerBoundTraceEventHandler155         BoundTraceEventHandler() : instance(0), method(0) { }
BoundTraceEventHandlerBoundTraceEventHandler156         BoundTraceEventHandler(TraceEventTargetBase* instance, TraceEventHandlerMethod method)
157             : instance(instance)
158             , method(method)
159         {
160         }
161     };
162     typedef std::pair<String, int> EventSelector;
163     typedef HashMap<EventSelector, Vector<BoundTraceEventHandler> > HandlersMap;
164 
TraceEventDispatcher()165     TraceEventDispatcher()
166         : m_processEventsTaskInFlight(false)
167         , m_lastEventProcessingTime(0)
168     {
169     }
170 
171     static void dispatchEventOnAnyThread(char phase, const unsigned char*, const char* name, unsigned long long id,
172         int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
173         unsigned char flags, double timestamp);
174 
175     void enqueueEvent(const TraceEvent&);
176     void innerAddListener(const char* name, char phase, TraceEventTargetBase*, TraceEventHandlerMethod, InspectorClient*);
177     void processBackgroundEventsTask();
178 
179     Mutex m_mutex;
180     HandlersMap m_handlers;
181     Vector<TraceEvent> m_backgroundEvents;
182     bool m_processEventsTaskInFlight;
183     double m_lastEventProcessingTime;
184 };
185 
186 template<typename C> struct TraceEventTarget : public TraceEventTargetBase {
187     typedef void (C::*TraceEventHandler)(const TraceEventDispatcher::TraceEvent&);
188 };
189 
190 } // namespace WebCore
191 
192 #endif // TraceEventDispatcher_h
193