| OLD | NEW |
| (Empty) |
| 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*>(argumen
tValues[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_TYP
E_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, un
signed 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 th
eir 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<TraceEventLis
tener> { | |
| 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<TraceE
ventListener>, 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(const TraceEvent&); | |
| 176 void processBackgroundEventsTask(); | |
| 177 | |
| 178 Mutex m_mutex; | |
| 179 OwnPtrWillBePersistent<ListenersMap> m_listeners; | |
| 180 Vector<TraceEvent> m_backgroundEvents; | |
| 181 bool m_processEventsTaskInFlight; | |
| 182 double m_lastEventProcessingTime; | |
| 183 }; | |
| 184 | |
| 185 } // namespace blink | |
| 186 | |
| 187 #endif // TraceEventDispatcher_h | |
| OLD | NEW |