Home | History | Annotate | Download | only in events
      1 /*
      2  * Copyright (C) 2012 Apple 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
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef EventSender_h
     27 #define EventSender_h
     28 
     29 #include "platform/Timer.h"
     30 #include "wtf/Vector.h"
     31 #include "wtf/text/AtomicString.h"
     32 
     33 namespace blink {
     34 
     35 template<typename T> class EventSender {
     36     WTF_MAKE_NONCOPYABLE(EventSender); WTF_MAKE_FAST_ALLOCATED;
     37 public:
     38     explicit EventSender(const AtomicString& eventType);
     39 
     40     const AtomicString& eventType() const { return m_eventType; }
     41     void dispatchEventSoon(T*);
     42     void cancelEvent(T*);
     43     void dispatchPendingEvents();
     44 
     45 #if ENABLE(ASSERT)
     46     bool hasPendingEvents(T* sender) const
     47     {
     48         return m_dispatchSoonList.find(sender) != kNotFound || m_dispatchingList.find(sender) != kNotFound;
     49     }
     50 #endif
     51 
     52 private:
     53     void timerFired(Timer<EventSender<T> >*) { dispatchPendingEvents(); }
     54 
     55     AtomicString m_eventType;
     56     Timer<EventSender<T> > m_timer;
     57     WillBePersistentHeapVector<RawPtrWillBeMember<T> > m_dispatchSoonList;
     58     WillBePersistentHeapVector<RawPtrWillBeMember<T> > m_dispatchingList;
     59 };
     60 
     61 template<typename T> EventSender<T>::EventSender(const AtomicString& eventType)
     62     : m_eventType(eventType)
     63     , m_timer(this, &EventSender::timerFired)
     64 {
     65 }
     66 
     67 template<typename T> void EventSender<T>::dispatchEventSoon(T* sender)
     68 {
     69     m_dispatchSoonList.append(sender);
     70     if (!m_timer.isActive())
     71         m_timer.startOneShot(0, FROM_HERE);
     72 }
     73 
     74 template<typename T> void EventSender<T>::cancelEvent(T* sender)
     75 {
     76     // Remove instances of this sender from both lists.
     77     // Use loops because we allow multiple instances to get into the lists.
     78     size_t size = m_dispatchSoonList.size();
     79     for (size_t i = 0; i < size; ++i) {
     80         if (m_dispatchSoonList[i] == sender)
     81             m_dispatchSoonList[i] = nullptr;
     82     }
     83     size = m_dispatchingList.size();
     84     for (size_t i = 0; i < size; ++i) {
     85         if (m_dispatchingList[i] == sender)
     86             m_dispatchingList[i] = nullptr;
     87     }
     88 }
     89 
     90 template<typename T> void EventSender<T>::dispatchPendingEvents()
     91 {
     92     // Need to avoid re-entering this function; if new dispatches are
     93     // scheduled before the parent finishes processing the list, they
     94     // will set a timer and eventually be processed.
     95     if (!m_dispatchingList.isEmpty())
     96         return;
     97 
     98     m_timer.stop();
     99 
    100     m_dispatchingList.swap(m_dispatchSoonList);
    101     size_t size = m_dispatchingList.size();
    102     for (size_t i = 0; i < size; ++i) {
    103         if (T* sender = m_dispatchingList[i]) {
    104             m_dispatchingList[i] = nullptr;
    105             sender->dispatchPendingEvent(this);
    106         }
    107     }
    108     m_dispatchingList.clear();
    109 }
    110 
    111 } // namespace blink
    112 
    113 #endif // EventSender_h
    114