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 "platform/heap/Handle.h" 36 #include "wtf/HashMap.h" 37 #include "wtf/Threading.h" 38 #include "wtf/ThreadingPrimitives.h" 39 #include "wtf/Vector.h" 40 #include "wtf/text/StringHash.h" 41 #include "wtf/text/WTFString.h" 42 43 namespace blink { 44 45 class InspectorClient; 46 47 class TraceEventDispatcher { 48 WTF_MAKE_NONCOPYABLE(TraceEventDispatcher); 49 public: 50 class TraceEvent { 51 public: 52 TraceEvent() 53 : m_name(0) 54 , m_argumentCount(0) 55 { 56 } 57 58 TraceEvent(double timestamp, char phase, const char* name, unsigned long long id, ThreadIdentifier threadIdentifier, 59 int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues) 60 : m_timestamp(timestamp) 61 , m_phase(phase) 62 , m_name(name) 63 , m_id(id) 64 , m_threadIdentifier(threadIdentifier) 65 , m_argumentCount(argumentCount) 66 { 67 if (m_argumentCount > MaxArguments) { 68 ASSERT_NOT_REACHED(); 69 m_argumentCount = MaxArguments; 70 } 71 for (int i = 0; i < m_argumentCount; ++i) { 72 m_argumentNames[i] = argumentNames[i]; 73 if (argumentTypes[i] == TRACE_VALUE_TYPE_COPY_STRING) { 74 m_stringArguments[i] = reinterpret_cast<const char*>(argumentValues[i]); 75 m_argumentValues[i].m_string = reinterpret_cast<const char*>(m_stringArguments[i].characters8()); 76 m_argumentTypes[i] = TRACE_VALUE_TYPE_STRING; 77 } else { 78 m_argumentValues[i].m_int = argumentValues[i]; 79 m_argumentTypes[i] = argumentTypes[i]; 80 } 81 } 82 } 83 84 double timestamp() const { return m_timestamp; } 85 char phase() const { return m_phase; } 86 const char* name() const { return m_name; } 87 unsigned long long id() const { return m_id; } 88 ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; } 89 int argumentCount() const { return m_argumentCount; } 90 bool isNull() const { return !m_name; } 91 92 bool asBool(const char* name) const 93 { 94 return parameter(name, TRACE_VALUE_TYPE_BOOL).m_bool; 95 } 96 long long asInt(const char* name) const 97 { 98 size_t index = findParameter(name); 99 if (index == kNotFound || (m_argumentTypes[index] != TRACE_VALUE_TYPE_INT && m_argumentTypes[index] != TRACE_VALUE_TYPE_UINT)) { 100 ASSERT_NOT_REACHED(); 101 return 0; 102 } 103 return reinterpret_cast<const blink::TraceEvent::TraceValueUnion*>(m_argumentValues + index)->m_int; 104 } 105 unsigned long long asUInt(const char* name) const 106 { 107 return asInt(name); 108 } 109 double asDouble(const char* name) const 110 { 111 return parameter(name, TRACE_VALUE_TYPE_DOUBLE).m_double; 112 } 113 const char* asString(const char* name) const 114 { 115 return parameter(name, TRACE_VALUE_TYPE_STRING).m_string; 116 } 117 118 private: 119 enum { MaxArguments = 2 }; 120 121 size_t findParameter(const char*) const; 122 const blink::TraceEvent::TraceValueUnion& parameter(const char* name, unsigned char expectedType) const; 123 124 double m_timestamp; 125 char m_phase; 126 const char* m_name; 127 unsigned long long m_id; 128 ThreadIdentifier m_threadIdentifier; 129 int m_argumentCount; 130 const char* m_argumentNames[MaxArguments]; 131 unsigned char m_argumentTypes[MaxArguments]; 132 blink::TraceEvent::TraceValueUnion m_argumentValues[MaxArguments]; 133 // These are only used as buffers for TRACE_VALUE_TYPE_COPY_STRING. 134 // Consider allocating the entire vector of buffered trace events and their copied arguments out of a special arena 135 // to make things more compact. 136 String m_stringArguments[MaxArguments]; 137 }; 138 139 class TraceEventListener : public NoBaseWillBeGarbageCollected<TraceEventListener> { 140 public: 141 #if !ENABLE(OILPAN) 142 virtual ~TraceEventListener() { } 143 #endif 144 virtual void call(const TraceEventDispatcher::TraceEvent&) = 0; 145 virtual void* target() = 0; 146 virtual void trace(Visitor*) { } 147 }; 148 149 static TraceEventDispatcher* instance() 150 { 151 DEFINE_STATIC_LOCAL(TraceEventDispatcher, instance, ()); 152 return &instance; 153 } 154 155 void addListener(const char* name, char phase, PassOwnPtrWillBeRawPtr<TraceEventListener>, InspectorClient*); 156 157 void removeAllListeners(void*, InspectorClient*); 158 void processBackgroundEvents(); 159 160 private: 161 typedef std::pair<String, int> EventSelector; 162 typedef WillBeHeapHashMap<EventSelector, OwnPtrWillBeMember<WillBeHeapVector<OwnPtrWillBeMember<TraceEventListener> > > > ListenersMap; 163 164 TraceEventDispatcher() 165 : m_listeners(adoptPtrWillBeNoop(new ListenersMap())) 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(double timestamp, char phase, const char* name, unsigned long long id, ThreadIdentifier, 176 int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues); 177 void processBackgroundEventsTask(); 178 179 Mutex m_mutex; 180 OwnPtrWillBePersistent<ListenersMap> m_listeners; 181 Vector<TraceEvent> m_backgroundEvents; 182 bool m_processEventsTaskInFlight; 183 double m_lastEventProcessingTime; 184 }; 185 186 } // namespace blink 187 188 #endif // TraceEventDispatcher_h 189