2010-10-21 76 views
13

我一直在寫一些代碼,取代一些現有的:GCD Dispatch Sources和select()有什麼區別?

while(runEventLoop){ 
    if(select(openSockets, readFDS, writeFDS, errFDS, timeout) > 0){ 
    // check file descriptors for activity and dispatch events based on same 
    } 
} 

插座識別代碼。我想將其改爲使用GCD隊列,以便我可以使用dispatch_async將事件彈出到隊列中,而不是維護「必須在下一次迭代時調用」數組。我也已經使用GCD隊列來包含/包含這個特定的動作,因此想要將它轉換爲更自然的GCD調度表單。 (不是while()循環壟斷串行隊列)

然而,當我試圖重構成依靠調度來源從綁DISPATCH_SOURCE_TYPE_READ和DISPATCH_SOURCE_TYPE_WRITE的插座描述符,庫代碼的事件處理程序發射的形式這一點,依靠這個調度停止工作。我的第一個假設是我誤解了DISPATCH_SOURCE_TYPE_READ和DISPATCH_SOURCE_TYPE_WRITE的使用 - 我曾假設他們會產生與使用這些套接字描述符調用select()大致相同的行爲。

我是否誤解GCD調度源?或者,關於重構,我是否在最不適合的情況下使用它?

+0

你應該顯示你的代碼 - 你做了什麼。與此同時,Mike Ash有一些示例代碼可以檢查 - http://www.mikeash.com/svn/GCDWeb/GCDWeb.m - GCD Web服務器。 – robertvojta 2011-02-26 16:35:14

回答

3

你的問題的簡短答案是:無。沒有任何區別,GCD調度源和select()都做同樣的事情:它們通知用戶特定內核事件發生或特定條件成立。

請注意,在Mac或iOS設備上,您不應使用select(),而應使用更高級的kqueue()kevent()(或kevent64())。

您當然可以將代碼轉換爲使用GCD調度源,但您需要注意不要打破依賴於此的其他代碼。因此,這需要對整個代碼處理信號,文件描述符,套接字以及所有其他低級內核事件進行全面檢查。

可能更簡單的解決方案可能是維護原始代碼,只需在對事件作出反應的部分添加GCD代碼。在這裏,您根據事件的特定類型在不同的隊列上分派事件。

+0

我同意,與GCD不同的是,您可以將代碼模塊化爲單獨的狀態機,並使用與每個源關聯的獨立調度隊列。我不確定,但我想內部GCD可能會使用類似的東西來選擇自己。 – user210504 2011-03-04 19:25:44

+2

你可以更具體地說明爲什麼kqueue()比iOS上的select()更好嗎?從我簡短的探討中,當你有很多要監視的事件時,看起來好像是kqueue(),但是有什麼理由相信它比單個fd的fdset上的select()更好?在這種情況下,似乎語義幾乎相同,所以不確定爲什麼性能會有所不同? – user1055568 2013-10-02 17:54:23

+1

表演實際上是不同的:只爲自己嘗試。您應該看到,即使對於具有激烈活動的單個文件描述符,kqueue()也會更好。可能蘋果並沒有太多改進舊的select()實現。新的queue()系統調用功能更強大,性能更好。我看到使用select()的唯一原因是您有不想更新的遺留代碼。 – 2013-10-03 06:23:17