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 { 46 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: 56 TraceEvent() 57 : m_name(0) 58 , m_argumentCount(0) 59 { 60 } 61 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 82 double timestamp() const { return m_timestamp; } 83 char phase() const { return m_phase; } 84 const char* name() const { return m_name; } 85 unsigned long long id() const { return m_id; } 86 ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; } 87 int argumentCount() const { return m_argumentCount; } 88 bool isNull() const { return !m_name; } 89 90 bool asBool(const char* name) const 91 { 92 return parameter(name, TRACE_VALUE_TYPE_BOOL).m_bool; 93 } 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 } 103 unsigned long long asUInt(const char* name) const 104 { 105 return asInt(name); 106 } 107 double asDouble(const char* name) const 108 { 109 return parameter(name, TRACE_VALUE_TYPE_DOUBLE).m_double; 110 } 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 135 static TraceEventDispatcher* instance() 136 { 137 DEFINE_STATIC_LOCAL(TraceEventDispatcher, instance, ()); 138 return &instance; 139 } 140 141 template<typename ListenerClass> 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 155 BoundTraceEventHandler() : instance(0), method(0) { } 156 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 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