]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/mac/MainThreadMac.mm
JavaScriptCore-621.1.tar.gz
[apple/javascriptcore.git] / wtf / mac / MainThreadMac.mm
index 0ddd5f64ea28a0726792c9ebabf8385c0f8250b5..aabaafa19056d176befab19df275497666d710ce 100644 (file)
 #import "config.h"
 #import "MainThread.h"
 
+#import <CoreFoundation/CoreFoundation.h>
 #import <Foundation/NSThread.h>
+#import <stdio.h>
 #import <wtf/Assertions.h>
+#import <wtf/Threading.h>
 
 @interface WTFMainThreadCaller : NSObject {
 }
 
 namespace WTF {
 
-static WTFMainThreadCaller* staticMainThreadCaller = nil;
-#if USE(WEB_THREAD)
-static NSThread* webThread = nil;
-#endif
+static WTFMainThreadCaller* staticMainThreadCaller;
+static bool isTimerPosted; // This is only accessed on the 'main' thread.
+static bool mainThreadEstablishedAsPthreadMain;
+static pthread_t mainThreadPthread;
+static NSThread* mainThreadNSThread;
 
 void initializeMainThreadPlatform()
 {
+#if !defined(BUILDING_ON_TIGER)
     ASSERT(!staticMainThreadCaller);
     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
 
-#if USE(WEB_THREAD)
-    webThread = [[NSThread currentThread] retain];
+    mainThreadEstablishedAsPthreadMain = false;
+    mainThreadPthread = pthread_self();
+    mainThreadNSThread = [[NSThread currentThread] retain];
+#else
+    ASSERT_NOT_REACHED();
 #endif
 }
 
+void initializeMainThreadToProcessMainThreadPlatform()
+{
+    if (!pthread_main_np())
+        NSLog(@"WebKit Threading Violation - initial use of WebKit from a secondary thread.");
+
+    ASSERT(!staticMainThreadCaller);
+    staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
+
+    mainThreadEstablishedAsPthreadMain = true;
+    mainThreadPthread = 0;
+    mainThreadNSThread = nil;
+}
+
+static void timerFired(CFRunLoopTimerRef timer, void*)
+{
+    CFRelease(timer);
+    isTimerPosted = false;
+    WTF::dispatchFunctionsFromMainThread();
+}
+
+static void postTimer()
+{
+    ASSERT(isMainThread());
+
+    if (isTimerPosted)
+        return;
+
+    isTimerPosted = true;
+    CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreate(0, 0, 0, 0, 0, timerFired, 0), kCFRunLoopCommonModes);
+}
+
 void scheduleDispatchFunctionsOnMainThread()
 {
     ASSERT(staticMainThreadCaller);
-#if USE(WEB_THREAD)
-    [staticMainThreadCaller performSelector:@selector(call) onThread:webThread withObject:nil waitUntilDone:NO];
+
+    if (isMainThread()) {
+        postTimer();
+        return;
+    }
+
+    if (mainThreadEstablishedAsPthreadMain) {
+        ASSERT(!mainThreadNSThread);
+        [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
+        return;
+    }
+
+#if !defined(BUILDING_ON_TIGER)
+    ASSERT(mainThreadNSThread);
+    [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
 #else
-    [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
+    ASSERT_NOT_REACHED();
 #endif
 }
 
+bool isMainThread()
+{
+    if (mainThreadEstablishedAsPthreadMain) {
+        ASSERT(!mainThreadPthread);
+        return pthread_main_np();
+    }
+
+#if !defined(BUILDING_ON_TIGER)
+    ASSERT(mainThreadPthread);
+    return pthread_equal(pthread_self(), mainThreadPthread);
+#else
+    ASSERT_NOT_REACHED();
+    return false;
+#endif
+}
+
+// This function is the same as isMainThread() above except that it does not do
+// a ASSERT(mainThreadPthread). This should only be used by code that can get
+// invoked when the WebThread hasn't been started. See <rdar://8502487>.
+bool isWebThread()
+{
+    ASSERT(!mainThreadEstablishedAsPthreadMain);
+    return pthread_equal(pthread_self(), mainThreadPthread);
+}
+
 } // namespace WTF