]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/mac/MainThreadMac.mm
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / wtf / mac / MainThreadMac.mm
index b04ef0e427b0058f3e6f05e2da01f358132829a0..d8b5a40e3d9f1ce16a12eeed769e62973b66f719 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;
+static bool isTimerPosted; // This is only accessed on the 'main' thread.
+static bool mainThreadEstablishedAsPthreadMain;
+static pthread_t mainThreadPthread;
+static NSThread* mainThreadNSThread;
+
+void initializeMainThreadPlatform()
+{
+    ASSERT(!staticMainThreadCaller);
+    staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
+
+    mainThreadEstablishedAsPthreadMain = false;
+    mainThreadPthread = pthread_self();
+    mainThreadNSThread = [[NSThread currentThread] retain];
+}
+
+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()
 {
-    WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
-    [caller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
-    [caller release];
+    ASSERT(staticMainThreadCaller);
+
+    if (isMainThread()) {
+        postTimer();
+        return;
+    }
+
+    if (mainThreadEstablishedAsPthreadMain) {
+        ASSERT(!mainThreadNSThread);
+        [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
+        return;
+    }
+
+    ASSERT(mainThreadNSThread);
+    [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
+}
+
+bool isMainThread()
+{
+    if (mainThreadEstablishedAsPthreadMain) {
+        ASSERT(!mainThreadPthread);
+        return pthread_main_np();
+    }
+
+    ASSERT(mainThreadPthread);
+    return pthread_equal(pthread_self(), mainThreadPthread);
+}
+
+// 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