Home | History | Annotate | Download | only in inspector
      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