WebKit2/Platform/mac/WorkQueueMac.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2010 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 #include "WorkQueue.h"
       
    27 
       
    28 #include <mach/mach_port.h>
       
    29 #include <wtf/PassOwnPtr.h>
       
    30 
       
    31 #if HAVE(DISPATCH_H)
       
    32 
       
    33 void WorkQueue::executeWorkItem(void* item)
       
    34 {
       
    35     WorkQueue* queue = static_cast<WorkQueue*>(dispatch_get_context(dispatch_get_current_queue()));
       
    36     OwnPtr<WorkItem> workItem(static_cast<WorkItem*>(item));
       
    37     
       
    38     {
       
    39         MutexLocker locker(queue->m_isValidMutex);
       
    40         if (!queue->m_isValid)
       
    41             return;
       
    42     }
       
    43     
       
    44     workItem->execute();
       
    45 }
       
    46 
       
    47 void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
       
    48 {
       
    49     dispatch_async_f(m_dispatchQueue, item.leakPtr(), executeWorkItem);
       
    50 }
       
    51 
       
    52 class WorkQueue::EventSource {
       
    53 public:
       
    54     EventSource(MachPortEventType eventType, dispatch_source_t dispatchSource, PassOwnPtr<WorkItem> workItem)
       
    55         : m_eventType(eventType)
       
    56         , m_dispatchSource(dispatchSource)
       
    57         , m_workItem(workItem)
       
    58     {
       
    59     }
       
    60     
       
    61     dispatch_source_t dispatchSource() const { return m_dispatchSource; }
       
    62     
       
    63     static void eventHandler(void* source) 
       
    64     {
       
    65         EventSource* eventSource = static_cast<EventSource*>(source);
       
    66         
       
    67         eventSource->m_workItem->execute();
       
    68     }
       
    69     
       
    70     static void cancelHandler(void* source)
       
    71     {
       
    72         EventSource* eventSource = static_cast<EventSource*>(source);
       
    73         
       
    74         mach_port_t machPort = dispatch_source_get_handle(eventSource->m_dispatchSource);
       
    75         
       
    76         switch (eventSource->m_eventType) {
       
    77         case MachPortDataAvailable:
       
    78             // Release our receive right.
       
    79             mach_port_mod_refs(mach_task_self(), machPort, MACH_PORT_RIGHT_RECEIVE, -1);
       
    80             break;
       
    81         case MachPortDeadNameNotification:
       
    82             // Release our send right.
       
    83             mach_port_deallocate(mach_task_self(), machPort);
       
    84             break;
       
    85         }
       
    86     }
       
    87     
       
    88     static void finalizeHandler(void* source)
       
    89     {
       
    90         EventSource* eventSource = static_cast<EventSource*>(source);
       
    91         
       
    92         delete eventSource;
       
    93     }
       
    94     
       
    95 private:
       
    96     MachPortEventType m_eventType;
       
    97     
       
    98     // This is a weak reference, since m_dispatchSource references the event source.
       
    99     dispatch_source_t m_dispatchSource;
       
   100     
       
   101     OwnPtr<WorkItem> m_workItem;
       
   102 };
       
   103 
       
   104 void WorkQueue::registerMachPortEventHandler(mach_port_t machPort, MachPortEventType eventType, PassOwnPtr<WorkItem> workItem)
       
   105 {
       
   106     dispatch_source_type_t sourceType = 0;
       
   107     switch (eventType) {
       
   108     case MachPortDataAvailable:
       
   109         sourceType = DISPATCH_SOURCE_TYPE_MACH_RECV;
       
   110         break;
       
   111     case MachPortDeadNameNotification:
       
   112         sourceType = DISPATCH_SOURCE_TYPE_MACH_SEND;
       
   113         break;
       
   114     }
       
   115     
       
   116     dispatch_source_t dispatchSource = dispatch_source_create(sourceType, machPort, 0, m_dispatchQueue);
       
   117     
       
   118     EventSource* eventSource = new EventSource(eventType, dispatchSource, workItem);
       
   119     dispatch_set_context(dispatchSource, eventSource);
       
   120     
       
   121     dispatch_source_set_event_handler_f(dispatchSource, &EventSource::eventHandler);
       
   122     dispatch_source_set_cancel_handler_f(dispatchSource, &EventSource::cancelHandler);
       
   123     dispatch_set_finalizer_f(dispatchSource, &EventSource::finalizeHandler);
       
   124     
       
   125     // Add the source to our set of sources.
       
   126     {
       
   127         MutexLocker locker(m_eventSourcesMutex);
       
   128         
       
   129         ASSERT(!m_eventSources.contains(machPort));
       
   130         
       
   131         m_eventSources.set(machPort, eventSource);
       
   132         
       
   133         // And start it!
       
   134         dispatch_resume(dispatchSource);
       
   135     }
       
   136 }
       
   137 
       
   138 void WorkQueue::unregisterMachPortEventHandler(mach_port_t machPort)
       
   139 {
       
   140     ASSERT(machPort);
       
   141     
       
   142     MutexLocker locker(m_eventSourcesMutex);
       
   143     
       
   144     HashMap<mach_port_t, EventSource*>::iterator it = m_eventSources.find(machPort);
       
   145     ASSERT(it != m_eventSources.end());
       
   146     
       
   147     ASSERT(m_eventSources.contains(machPort));
       
   148 
       
   149     EventSource* eventSource = it->second;
       
   150     // Cancel and release the source. It will be deleted in its finalize handler.
       
   151     dispatch_source_cancel(eventSource->dispatchSource());
       
   152     dispatch_release(eventSource->dispatchSource());
       
   153 
       
   154     m_eventSources.remove(it);    
       
   155 }
       
   156 
       
   157 void WorkQueue::platformInitialize(const char* name)
       
   158 {
       
   159     m_dispatchQueue = dispatch_queue_create(name, 0);
       
   160     dispatch_set_context(m_dispatchQueue, this);
       
   161 }
       
   162 
       
   163 void WorkQueue::platformInvalidate()
       
   164 {
       
   165 #if !ASSERT_DISABLED
       
   166     MutexLocker locker(m_eventSourcesMutex);
       
   167     ASSERT(m_eventSources.isEmpty());
       
   168 #endif
       
   169 }
       
   170 
       
   171 #else /* !HAVE(DISPATCH_H) */
       
   172 
       
   173 void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
       
   174 {
       
   175 }
       
   176 
       
   177 void WorkQueue::registerMachPortEventHandler(mach_port_t, MachPortEventType, PassOwnPtr<WorkItem>)
       
   178 {
       
   179 }
       
   180 
       
   181 void WorkQueue::unregisterMachPortEventHandler(mach_port_t)
       
   182 {
       
   183 }
       
   184 
       
   185 void WorkQueue::platformInitialize(const char*)
       
   186 {
       
   187 }
       
   188 
       
   189 void WorkQueue::platformInvalidate()
       
   190 {
       
   191 }
       
   192 
       
   193 #endif