Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (C) 2007, 2008 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  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #import "config.h"
     30 #import "MainThread.h"
     31 
     32 #import <CoreFoundation/CoreFoundation.h>
     33 #import <Foundation/NSThread.h>
     34 #import <stdio.h>
     35 #import <wtf/Assertions.h>
     36 #import <wtf/Threading.h>
     37 
     38 @interface WTFMainThreadCaller : NSObject {
     39 }
     40 - (void)call;
     41 @end
     42 
     43 @implementation WTFMainThreadCaller
     44 
     45 - (void)call
     46 {
     47     WTF::dispatchFunctionsFromMainThread();
     48 }
     49 
     50 @end // implementation WTFMainThreadCaller
     51 
     52 namespace WTF {
     53 
     54 static WTFMainThreadCaller* staticMainThreadCaller;
     55 static bool isTimerPosted; // This is only accessed on the 'main' thread.
     56 static bool mainThreadEstablishedAsPthreadMain;
     57 static pthread_t mainThreadPthread;
     58 static NSThread* mainThreadNSThread;
     59 
     60 void initializeMainThreadPlatform()
     61 {
     62 #if !defined(BUILDING_ON_TIGER)
     63     ASSERT(!staticMainThreadCaller);
     64     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
     65 
     66     mainThreadEstablishedAsPthreadMain = false;
     67     mainThreadPthread = pthread_self();
     68     mainThreadNSThread = [[NSThread currentThread] retain];
     69 #else
     70     ASSERT_NOT_REACHED();
     71 #endif
     72 }
     73 
     74 void initializeMainThreadToProcessMainThreadPlatform()
     75 {
     76     if (!pthread_main_np())
     77         NSLog(@"WebKit Threading Violation - initial use of WebKit from a secondary thread.");
     78 
     79     ASSERT(!staticMainThreadCaller);
     80     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
     81 
     82     mainThreadEstablishedAsPthreadMain = true;
     83     mainThreadPthread = 0;
     84     mainThreadNSThread = nil;
     85 }
     86 
     87 static void timerFired(CFRunLoopTimerRef timer, void*)
     88 {
     89     CFRelease(timer);
     90     isTimerPosted = false;
     91     WTF::dispatchFunctionsFromMainThread();
     92 }
     93 
     94 static void postTimer()
     95 {
     96     ASSERT(isMainThread());
     97 
     98     if (isTimerPosted)
     99         return;
    100 
    101     isTimerPosted = true;
    102     CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreate(0, 0, 0, 0, 0, timerFired, 0), kCFRunLoopCommonModes);
    103 }
    104 
    105 void scheduleDispatchFunctionsOnMainThread()
    106 {
    107     ASSERT(staticMainThreadCaller);
    108 
    109     if (isMainThread()) {
    110         postTimer();
    111         return;
    112     }
    113 
    114     if (mainThreadEstablishedAsPthreadMain) {
    115         ASSERT(!mainThreadNSThread);
    116         [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
    117         return;
    118     }
    119 
    120 #if !defined(BUILDING_ON_TIGER)
    121     ASSERT(mainThreadNSThread);
    122     [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
    123 #else
    124     ASSERT_NOT_REACHED();
    125 #endif
    126 }
    127 
    128 bool isMainThread()
    129 {
    130     if (mainThreadEstablishedAsPthreadMain) {
    131         ASSERT(!mainThreadPthread);
    132         return pthread_main_np();
    133     }
    134 
    135 #if !defined(BUILDING_ON_TIGER)
    136     ASSERT(mainThreadPthread);
    137     return pthread_equal(pthread_self(), mainThreadPthread);
    138 #else
    139     ASSERT_NOT_REACHED();
    140     return false;
    141 #endif
    142 }
    143 
    144 } // namespace WTF
    145