iOS的WebThread

当用到UIWebView、UITextField、UITextView等类时,就会看到WebThread线程:

iOS的WebThread_第1张图片

在lldb中搜索

(lldb) image lookup -r -s [wW]ebThread
会有超过一百个结果。

对于普通开发者而言,WebThread最有意义的东西恐怕是UIWebView的私有API

- (void)_setDrawInWebThread:(BOOL)drawInWebThread;
设置YES后,会在WebThread进行渲染的某些操作(layoutTiles),不占用主线程。


Mac上的Safari是多进程程序,排版和渲染等是在独立的进程里。iOS不允许多进程,只有多线程,所以在iOS版的WebCore.framework里会有一些代码来把多进程机制适配成多线程机制,WebThread就是主要产物之一。


iOS的WebCore开源码,6.1版本的下载地址为:http://opensource.apple.com/release/ios-61/

比起webkit.org上的Mac开源码,会多了个wak目录,内有21个文件,其中与WebCoreThread相关的有6个。常见的被调用函数有这么一些:

// The lock is automatically freed at the bottom of the runloop. No need to unlock.
// Note that calling this function may hang your UI for several seconds. Don't use
// unless you have to.
void WebThreadLock(void);
    
// This is a no-op for compatibility only. It will go away. Please don't use.
void WebThreadUnlock(void);
    
// Please don't use anything below this line unless you know what you are doing. If unsure, ask.
// ---------------------------------------------------------------------------------------------
bool WebThreadIsLocked(void);
bool WebThreadIsLockedOrDisabled(void);
    
void WebThreadLockPushModal(void);
void WebThreadLockPopModal(void);

void WebThreadEnable(void);
bool WebThreadIsEnabled(void);
bool WebThreadIsCurrent(void);
bool WebThreadNotCurrent(void);
    
// These are for <rdar://problem/6817341> Many apps crashing calling -[UIFieldEditor text] in secondary thread
// Don't use them to solve any random problems you might have.
void WebThreadLockFromAnyThread();
void WebThreadLockFromAnyThreadNoLog();
void WebThreadUnlockFromAnyThread();

//
// Release an object on the main thread.
//
@interface NSObject(WebCoreThreadAdditions)
- (void)releaseOnMainThread;
@end

// Register a class for deallocation on the WebThread
void WebCoreObjCDeallocOnWebThread(Class cls);
void WebCoreObjCDeallocWithWebThreadLock(Class cls);

// Asynchronous from main thread to web thread.
void WebThreadCallAPI(NSInvocation *invocation); /* DEPRECATED; use WebThreadRun() in WebCoreThreadRun.h */
void WebThreadAdoptAndRelease(id obj);

// Synchronous from web thread to main thread, or main thread to main thread.
void WebThreadCallDelegate(NSInvocation *invocation);
void WebThreadRunOnMainThread(void (^)(void));

// Asynchronous from web thread to main thread, but synchronous when called on the main thread.
void WebThreadCallDelegateAsync(NSInvocation *invocation);

// Asynchronous from web thread to main thread, but synchronous when called on the main thread.
void WebThreadPostNotification(NSString *name, id object, id userInfo);

// Convenience method for making an NSInvocation object
NSInvocation *WebThreadMakeNSInvocation(id target, SEL selector);

UIKit只工作在main thread,WebCore工作在WebThread,当产生交集时就需要线程间通信,以上函数就是为了线程间消息服务的,最多的操作当然就是加锁了。具体的发消息实现有几种,RunLoop、GCD、performSelector、pthread都会用,也可谓复杂了。依我看应该是新老技术替换的结果,说不定还是新老员工的不同工作结果。

WebThread是以pthread创建的,有全局变量pthread_t webThread来做引用,在不少地方会有
pthread_equal(pthread_self(), webThread)
的判断。

模态机制用的是CFRunLoop。异步消息多用GCD。

在WebView和Clients间通信时,有两个类作为消息中转,_WebSafeForwarder和_WebSafeAsyncForwarder。


让人纠结的是,iOS的实现是在把单线程的Mac上的WebKit.framework改成多线程,但又没法用类似WebKit2.framework的那种多进程方案。WebKit.framework里诸多的WebHTMLView是会直接访问WebCore的,所以iOS上的WebKit.framework里多了好多的锁。为了避免被developer吐槽,这个框架就干脆不公开了,用UIWebView封装好,只有那几个简单的接口来做门面。

你可能感兴趣的:(ios,webkit,webcore,WebThread)