iOS多線程的初步研究(七)-- dispatch對象

談起iOS的dispatch(正式稱謂是Grand Central Dispatch或GCD),不得不說這又是iOS(包括MacOSX)平臺的創新,優缺點這裏不討論,只有當你使用時才能真正體會到。我們說dispatch函數的主要目的是實現多任務併發代碼,那麼要理解dispatch函數,先來了解dispatch對象的定義。

 

dispatch對象類型的部分定義,主要使用C語言的宏定義:

<os/object.h>文件:

#define OS_OBJECT_CLASS(name) OS_##name

#define OS_OBJECT_DECL(name, ...) \

@protocol OS_OBJECT_CLASS(name) __VA_ARGS__ \

@end \

typedef NSObject<OS_OBJECT_CLASS(name)> *name##_t

#define OS_OBJECT_DECL_SUBCLASS(name, super) \

OS_OBJECT_DECL(name, <OS_OBJECT_CLASS(super)>)

 

<dispatch/object.h>文件:

#define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)

#define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))

OS_OBJECT_DECL(dispatch_object); //定義dispatch_object_t

 

<dispatch/queue.h>文件(dispatch隊列類定義,其它dispatch對象類似):

DISPATCH_DECL(dispatch_queue); //定義dispatch_queue_t

 

可以通過Xcode預編譯後可以看到最終結果,最終定義的都是NSObject類,雖然它們之間沒用直接繼承關係,但都實現OS_dispatch_object接口,這樣dispatch_queue_t對象也同樣是dispatch_object_t的對象了。下面就是預編譯dispatch_object_t和dispatch_queue_t的結果:

@protocol OS_dispatch_object

@end

typedef NSObject<OS_dispatch_object> *dispatch_object_t;

@protocol OS_dispatch_queue <OS_dispatch_object>

@end

typedef NSObject<OS_dispatch_queue> *dispatch_queue_t;

 

由於dispatch api接口定義成C函數的形式,dispatch的對象都是由C函數形式的廠方法得到(不能繼承dispatch類,不用alloc),這樣做隱藏dispatch對象的具體形態,把注意力放在如何調用dispatch api上。

從上面dispatch對象宏定義可以看到dispatch對象類的名稱一般爲dispatch_xyz_t(嚴格來講是對象指針),它們都可以看成dispatch_object_t的子類(對象指針),所以使用dispatch對象時套用這個概念就行。

 

有關dispatch對象的基本接口如下:

void dispatch_retain(dispatch_object_t object); //替代dispatch對象常規的retain來持有對象,但ARC編程中不再允許

void dispatch_release(dispatch_object_t object); //替代dispatch對象常規的release來釋放對象,同樣ARC編程中不再允許

void dispatch_set_context(dispatch_object_t object, void *context); //給dispatch對象綁定特定數據對象(類似線程的TLS數據),會被傳給dispatch對象的finalizer函數

void *dispatch_get_context(dispatch_object_t object); //返回dispatch對象綁定的數據對象指針

void dispatch_set_finalizer_f(dispatch_object_t object, dispatch_function_t finalizer); //設置dispatch對象的finalizer函數,當該對象釋放時會調用finalizer,部分代碼解釋如何使用這個函數(ARC模式):

dispatch_object_t dispatchObject = ...;

void *context = ...;

dispatch_set_context(dispatchObject, context);

dispatch_set_finalizer_f(dispatchObject, finalizer);

......

dispatchObject = nil; //dispatchObject被釋放,這時調用finalizer函數

......

void finalizer(void *context)

{

  //處理或釋放context相關資源

}

 

dispatch對象的另外兩個接口是:

void dispatch_resume(dispatch_object_t object); //激活(啓動)在dispatch對象上的block調用,可以運行多個block

void dispatch_suspend(dispatch_object_t object); //掛起(暫停)在dispatch對象上的block調用,已經運行的block不會停止

一般這兩個函數的調用必須成對,否則運行會出現異常。

至此你是否發現這兩個函數有些與衆不同呢?好像從來沒有這麼使用對象的,啓動對象--暫停對象,呵呵。這正是理解dispatch對象的關鍵所在。dispatch對象其實是抽象的任務,把動態的任務變成對象來管理。任務是動態的,不存在繼承關係,這就是爲什麼GCD沒有提供靜態繼承dispatch對象類的方式。如果能這樣理解,那麼在使用dispatch函數時就能夠更靈活地去編寫代碼,實現各種併發的多任務代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章