專(zhuān)利名稱(chēng):在線性棧上高效恢復(fù)協(xié)同例程的制作方法
在線性棧上高效恢復(fù)協(xié)同例程
背景技術(shù):
在計(jì)算機(jī)科學(xué)中,協(xié)同例程是通常概括子例程并且可允許多個(gè)入口點(diǎn)以進(jìn)行掛起 和恢復(fù)執(zhí)行的程序組件。協(xié)同例程有時(shí)被用于實(shí)現(xiàn)協(xié)作任務(wù)、迭代器、無(wú)限列表和管道。雖 然子例程通常是后進(jìn)先出構(gòu)造,但協(xié)同例程的壽命可按其用途來(lái)規(guī)定。雖然子例程只能返 回一次,但協(xié)同例程可返回或讓步一次以上。雖然子例程的開(kāi)始通常是其唯一入口點(diǎn),但協(xié) 同例程的開(kāi)始是第一入口點(diǎn)且后續(xù)入口點(diǎn)可跟隨讓步(yield)命令。例如,同子例程一樣, 在協(xié)同例程中讓步可將結(jié)果和控制返回給調(diào)用方協(xié)同例程,但不同于子例程,在該協(xié)同例 程下次被調(diào)用時(shí),執(zhí)行可剛好在讓步調(diào)用之后開(kāi)始而非在協(xié)同例程開(kāi)頭開(kāi)始。由于協(xié)同例程可返回多次,因此有可能在后續(xù)調(diào)用時(shí)返回附加的值。其中后續(xù)調(diào) 用產(chǎn)生附加結(jié)果的協(xié)同例程常常被稱(chēng)為生成器。傳統(tǒng)子例程使用可在程序執(zhí)行開(kāi)頭被預(yù)分 配的單個(gè)棧。相反,由于協(xié)同例程能夠作為對(duì)等體調(diào)用其他協(xié)同例程,因此通常為協(xié)同例程 分配附加的棧。有時(shí),預(yù)分配?;蛘吒咚倬彺骖A(yù)先分配的棧。生成器還一般化子例程,并且常常被用于簡(jiǎn)化迭代器的編寫(xiě)。生成器中的讓步語(yǔ) 句通常不指定要跳轉(zhuǎn)到的協(xié)同例程,而是將值回傳給父例程。然而,仍然有可能在頂級(jí)分派 器例程的輔助下在生成器設(shè)施上實(shí)現(xiàn)協(xié)同例程,頂級(jí)分派器例程將控制顯式地傳遞給從生 成器傳回的令牌所標(biāo)識(shí)的子生成器。許多流行編程語(yǔ)言(包括C、C++和C#)由于基于棧的子例程實(shí)現(xiàn)的限制因而在該 語(yǔ)言內(nèi)不直接支持協(xié)同例程。在其中協(xié)同例程將在邏輯上被用于在可能的情況下實(shí)現(xiàn)一機(jī) 制的情形中,通常創(chuàng)建使用布爾標(biāo)志和其他狀態(tài)變量的組合來(lái)在調(diào)用之間維護(hù)內(nèi)部狀態(tài)的 子例程。條件語(yǔ)句導(dǎo)致基于狀態(tài)變量的值而執(zhí)行不同代碼路徑?;蛘?,實(shí)現(xiàn)開(kāi)關(guān)語(yǔ)句形式 的顯式狀態(tài)機(jī)。提供使用協(xié)同例程的替換方案的方法是使用線程。線程提供用于管理基本上同時(shí) 執(zhí)行的代碼片斷的實(shí)時(shí)協(xié)作交互的能力。線程通常被優(yōu)先調(diào)度。協(xié)同例程通常不是。由于 線程可在任何時(shí)刻被重新調(diào)度且能并發(fā)地執(zhí)行,因此使用線程的程序必須注意鎖定。相反, 由于協(xié)同例程只能在程序中的特定點(diǎn)被重新調(diào)度并且不并發(fā)地執(zhí)行,因此使用協(xié)同例程的 程序常常完全避免了鎖定問(wèn)題。在高級(jí)語(yǔ)言中實(shí)現(xiàn)協(xié)同例程的一種方法放棄了便攜性。相反,處理器系列專(zhuān)用的 實(shí)現(xiàn)對(duì)于函數(shù)是用匯編語(yǔ)言編寫(xiě)的,以節(jié)約和恢復(fù)協(xié)同例程上下文。必須注意這些函數(shù)的 使用和編寫(xiě),從而在協(xié)同例程共享相同棧時(shí)位于該棧上的變量不被覆寫(xiě)。因此,通常對(duì)于高 級(jí)語(yǔ)言中基于棧的協(xié)同例程,需要函數(shù)來(lái)創(chuàng)建替換棧并在替換棧之間跳轉(zhuǎn)??商峁┑谌龣C(jī) 器專(zhuān)用函數(shù)以創(chuàng)建用于新協(xié)同例程的上下文。傳統(tǒng)上,協(xié)同例程的棧大小是固定的且在執(zhí) 行期間不能增長(zhǎng)。通常,程序分配比所需的更大的棧以避免潛在的棧溢出。概述在使用單個(gè)線性機(jī)器調(diào)用棧在沒(méi)有直接協(xié)同例程支持的語(yǔ)言中執(zhí)行的計(jì)算機(jī)系 統(tǒng)中,驅(qū)動(dòng)程序例程控制協(xié)同例程執(zhí)行。當(dāng)協(xié)同例程最初被另一協(xié)同例程調(diào)用時(shí),被調(diào)用的 協(xié)同例程被放到棧上調(diào)用者的幀之上。協(xié)同例程被首次掛起時(shí),其所有棧幀向下直至驅(qū)動(dòng)程序棧幀并且包括驅(qū)動(dòng)程序棧幀被復(fù)制到堆。然而,若協(xié)同例程被再次掛起,則其棧幀不被 再次復(fù)制到堆。當(dāng)協(xié)同例程恢復(fù)時(shí),驅(qū)動(dòng)程序例程僅將葉例程放到棧上。盡管該方法中的 單個(gè)掛起對(duì)于深度d的棧將花費(fèi)0(d),但由于每一幀僅被復(fù)制到堆一次,因此該方法的總 分?jǐn)偝杀緸? (m),其中m是曾掛起的幀數(shù),且m通常小于被調(diào)用的總幀數(shù)η。若在葉例程中拋出異常,則驅(qū)動(dòng)程序例程檢測(cè)或抓住該異常。驅(qū)動(dòng)程序在棧上用 與調(diào)用者相關(guān)聯(lián)的棧幀來(lái)代替與被調(diào)用者(被調(diào)用)葉例程相關(guān)聯(lián)的棧幀。驅(qū)動(dòng)程序執(zhí)行 調(diào)用方例程,并且異常被再次拋出。提供本概述以便以簡(jiǎn)化形式介紹將在以下詳細(xì)描述中進(jìn)一步描述的一些概念。本 概述并非旨在標(biāo)識(shí)出要求保護(hù)的主題的關(guān)鍵特征或必要特征,亦非旨在用于限定要求保護(hù) 的主題的范圍。附圖簡(jiǎn)述在附圖中
圖1示出根據(jù)本文所公開(kāi)主題的各方面用于在線性棧上高效恢復(fù)協(xié)同例程的系 統(tǒng)100的示例;圖2是根據(jù)如關(guān)于圖1所描述的本文所公開(kāi)主題的各方面用于在線性棧上高效恢 復(fù)協(xié)同例程的方法200的示例的流程圖。圖3是示出其中可實(shí)現(xiàn)本文所公開(kāi)主題的各方面的計(jì)算環(huán)境的示例的框圖;以及圖4是根據(jù)本文所公開(kāi)主題的各方面的集成開(kāi)發(fā)環(huán)境的示例的框圖。詳細(xì)描述概覽根據(jù)本文所公開(kāi)主題的各方面,未掛起協(xié)同例程由調(diào)用棧機(jī)制來(lái)處理,其中該棧 隨著作出調(diào)用和從調(diào)用返回而增長(zhǎng)和收縮。然而,在協(xié)同例程首次掛起時(shí),執(zhí)行附加的調(diào)用 棧處理。發(fā)出掛起消息,并且調(diào)用棧的整個(gè)能恢復(fù)部分被從機(jī)器調(diào)用棧移除并被復(fù)制到堆。 將控制返回給驅(qū)動(dòng)程序方法(恢復(fù)器)的幀被復(fù)制到調(diào)用棧,從而恢復(fù)不會(huì)遞歸地重新激 活整個(gè)調(diào)用棧。相反,恢復(fù)器僅重新激活被稱(chēng)為葉幀的最頂部或最當(dāng)前幀。在協(xié)同例程掛 起時(shí),其不返回到其調(diào)用者,而是返回到已重新激活它的恢復(fù)器,該恢復(fù)器檢索將控制返回 到的合適地址。由編譯器執(zhí)行的狀態(tài)機(jī)轉(zhuǎn)換不循環(huán)以重復(fù)地重新激活被調(diào)用者直至被調(diào)用棧返 回。從調(diào)用方狀態(tài)機(jī)的觀點(diǎn)而言,當(dāng)被調(diào)用者返回時(shí),其要么同步地返回,在這種情形中,結(jié) 果(或異常)被自然地消耗且處理繼續(xù)進(jìn)行;要么返回包括掛起,在這種情形中,處理被掛 起,且期望處理將不恢復(fù)直至被調(diào)用者完成并且恢復(fù)器返回其結(jié)果。在線性棧上高效恢復(fù)協(xié)同例程術(shù)語(yǔ)協(xié)同例程是用于動(dòng)作序列的通用術(shù)語(yǔ)。協(xié)同例程類(lèi)似于程序,除了與程序不 同的是,協(xié)同例程可在執(zhí)行期間被暫停(掛起)并在以后恢復(fù)。恢復(fù)可通過(guò)客戶機(jī)請(qǐng)求來(lái) 自協(xié)同例程的輸出來(lái)發(fā)起。例如,在一些編程語(yǔ)言中,迭代器可被實(shí)現(xiàn)為協(xié)同例程,其任務(wù) 是按需產(chǎn)生集合的元素。一旦該協(xié)同例程已產(chǎn)生集合的一元素,其暫停。在需要下一個(gè)元 素時(shí),該協(xié)同例程恢復(fù)。該過(guò)程繼續(xù),直至不需要更多元素或者直至已產(chǎn)生了集合中的所有 元素?;謴?fù)可通過(guò)輸入變得可用來(lái)驅(qū)動(dòng)或發(fā)起。例如,協(xié)同例程可在所請(qǐng)求數(shù)據(jù)不可用時(shí)暫停,這可能在較長(zhǎng)等待時(shí)間通道上請(qǐng)求數(shù)據(jù)(例如,從盤(pán)讀取或者從網(wǎng)絡(luò)訪問(wèn)信息等) 時(shí)發(fā)生。恢復(fù)可由回調(diào)或事件發(fā)起或者可在所請(qǐng)求數(shù)據(jù)變得可用時(shí)以其他方式觸發(fā)。這種 類(lèi)型的情景很可能在采用異步編程技術(shù)時(shí)遇到。通常,當(dāng)一個(gè)程序調(diào)用另一個(gè)程序時(shí),調(diào)用方程序等待結(jié)果并隨后調(diào)用下一個(gè)程 序,等待其結(jié)果,依此類(lèi)推。相反,可從另一協(xié)同例程遞歸地調(diào)用一個(gè)或多個(gè)協(xié)同例程達(dá)到 無(wú)論任何遞歸深度。在第一協(xié)同例程在遞歸協(xié)同例程調(diào)用鏈中調(diào)用第二協(xié)同例程時(shí),當(dāng)?shù)?二協(xié)同例程暫停時(shí),第一協(xié)同例程暫停,依此類(lèi)推。遞歸程序調(diào)用和子例程調(diào)用在傳統(tǒng)上是經(jīng)由稱(chēng)為機(jī)器調(diào)用棧(也稱(chēng)為執(zhí)行棧、控 制棧、函數(shù)?;蜻\(yùn)行時(shí)棧)的低級(jí)數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)的。調(diào)用棧保持跟蹤每個(gè)有效被調(diào)用者 在完成執(zhí)行時(shí)將控制返回到的點(diǎn)?;钴S被調(diào)用者是已被調(diào)用但尚未通過(guò)返回調(diào)用者來(lái)完成 執(zhí)行的被調(diào)用者。被調(diào)用者使調(diào)用者的返回地址進(jìn)棧,并且在被調(diào)用者完成時(shí),被調(diào)用者使 該返回地址出棧并將控制轉(zhuǎn)移到該出棧的地址。因此,被放到棧上的信息隨著程序執(zhí)行而 增長(zhǎng)和收縮。所描述的調(diào)用棧自動(dòng)支持串行世界中的遞歸。取決于語(yǔ)言、操作系統(tǒng)和機(jī)器環(huán) 境,調(diào)用??煞?wù)附加函數(shù),包括存儲(chǔ)本地?cái)?shù)據(jù)、參數(shù)、邏輯運(yùn)算、指向當(dāng)前實(shí)例的指針(該 指針(this pointer))、外圍例程上下文和返回狀態(tài)。機(jī)器調(diào)用棧數(shù)據(jù)結(jié)構(gòu)由棧幀構(gòu)成,棧幀是包含被調(diào)用者狀態(tài)信息的取決于機(jī)器的 數(shù)據(jù)結(jié)構(gòu)。每個(gè)棧幀對(duì)應(yīng)于對(duì)子例程的調(diào)用,該子例程尚未通過(guò)返回而終止。調(diào)用棧頂部 的棧幀(葉幀)保持關(guān)于當(dāng)前執(zhí)行的子例程的信息。由子例程調(diào)用指令提供給被調(diào)用者的 返回地址通過(guò)被調(diào)用者將該值壓到調(diào)用棧上來(lái)保存。在被調(diào)用者返回時(shí),整個(gè)棧幀出棧并 且控制被返回給位于返回地址處的指令。通常,一個(gè)調(diào)用棧與進(jìn)程的每個(gè)任務(wù)或線程相關(guān) 聯(lián)。在高級(jí)編程語(yǔ)言環(huán)境中,通常不允許程序員操縱調(diào)用棧的存儲(chǔ)器。通常,程序員僅 能訪問(wèn)將在棧上執(zhí)行的函數(shù)的列表。C和C++的實(shí)現(xiàn)將單個(gè)線性(連續(xù))棧用作棧幀的存 儲(chǔ)。程序調(diào)用使返回地址進(jìn)棧,并且被調(diào)用者將棧上的空間分配給其自己的本地變量等。線 性棧機(jī)制在串行世界中高效地工作。然而,線性棧固有地不能處理以非串行方式掛起和恢 復(fù)的協(xié)同例程。因此,為了在不支持在機(jī)器調(diào)用棧級(jí)掛起和恢復(fù)協(xié)同例程的平臺(tái)上實(shí)現(xiàn)協(xié) 同例程調(diào)用,有時(shí)采用處理協(xié)同例程掛起和恢復(fù)的附加處理。在使用單個(gè)線性機(jī)器調(diào)用棧在沒(méi)有直接協(xié)同例程支持的語(yǔ)言中執(zhí)行的計(jì)算機(jī)系 統(tǒng)的協(xié)同例程的傳統(tǒng)實(shí)現(xiàn)中,通過(guò)將機(jī)器調(diào)用棧上與協(xié)同例程相關(guān)聯(lián)的棧幀存儲(chǔ)到模仿該 機(jī)器調(diào)用棧的堆中來(lái)掛起協(xié)同例程。堆是保留用于對(duì)象的存儲(chǔ)器區(qū)域并且與機(jī)器調(diào)用棧分 開(kāi)。在協(xié)同例程恢復(fù)時(shí),與該協(xié)同例程相關(guān)聯(lián)的所有棧幀從堆重構(gòu)到機(jī)器調(diào)用棧上。因此, 當(dāng)機(jī)器調(diào)用棧上與協(xié)同例程相關(guān)聯(lián)的協(xié)同例程深度為d時(shí),執(zhí)行協(xié)同例程的一個(gè)步驟(恢 復(fù)它,執(zhí)行其計(jì)算的一些部分,并隨后再次將它掛起)的時(shí)間至少為0(d)。若協(xié)同例程不被 掛起,則機(jī)器調(diào)用棧上與該協(xié)同例程相關(guān)聯(lián)的棧幀不被復(fù)制到堆。另一種已知方法在協(xié)同例程每次被調(diào)用時(shí)(而非等待直至協(xié)同例程被掛起)將該 協(xié)同例程的棧幀從機(jī)器調(diào)用棧復(fù)制到模仿該機(jī)器調(diào)用棧的堆。驅(qū)動(dòng)程序例程控制協(xié)同例程 執(zhí)行。在該方法中,在任何給定時(shí)間,與協(xié)同例程相關(guān)聯(lián)的僅兩個(gè)棧幀在機(jī)器調(diào)用棧上。在 機(jī)器調(diào)用棧上的與協(xié)同例程相關(guān)聯(lián)的這兩個(gè)棧幀為驅(qū)動(dòng)程序例程和代表協(xié)同例程的葉例 程的執(zhí)行的棧幀。葉例程是與協(xié)同例程相關(guān)聯(lián)的最頂部棧幀。在葉例程掛起時(shí),最頂部棧幀被從機(jī)器調(diào)用棧移除并被存儲(chǔ)到堆上。在葉例程的執(zhí)行恢復(fù)時(shí),該葉例程的所存儲(chǔ)棧幀 被重構(gòu)到機(jī)器調(diào)用棧上。在葉例程完成執(zhí)行并返回其調(diào)用者時(shí),驅(qū)動(dòng)程序例程將調(diào)用者的 棧幀放到棧頂作為新葉。若任何當(dāng)前執(zhí)行的葉例程調(diào)用另一個(gè)例程,則驅(qū)動(dòng)程序例程在調(diào) 用棧上用代表被調(diào)用者(被調(diào)用例程)的新葉例程來(lái)代替當(dāng)前執(zhí)行的葉例程。驅(qū)動(dòng)程序在 堆中保持跟蹤誰(shuí)調(diào)用誰(shuí)以及協(xié)同例程被調(diào)用的次序。第二種方法允許協(xié)同例程在恒定的時(shí) 間里被調(diào)用、掛起、恢復(fù)和返回。然而,所有協(xié)同例程棧幀被復(fù)制到堆至少一次,即使協(xié)同例 程不被掛起。根據(jù)本文所公開(kāi)主題的各方面,幀僅在它們實(shí)際上曾被掛起時(shí)才被復(fù)制到堆。而 且,給定幀僅被復(fù)制到堆一次。驅(qū)動(dòng)程序例程在棧的協(xié)同例程部分的底部。當(dāng)協(xié)同例程最 初被另一協(xié)同例程調(diào)用時(shí),被調(diào)用協(xié)同例程將不在棧上代替其調(diào)用者,(從而被調(diào)用協(xié)同例 程的幀隨后將直接位于驅(qū)動(dòng)程序例程之上)。相反,被調(diào)用例程將以正常子例程的方式被調(diào) 用,且被調(diào)用例程的幀被放在棧上調(diào)用者的幀之上。當(dāng)首次掛起時(shí),棧上向下直至驅(qū)動(dòng)程序 例程的每一幀皆被復(fù)制到堆。在恢復(fù)時(shí),驅(qū)動(dòng)程序例程僅將葉例程放回棧上,并且通過(guò)在棧 上用調(diào)用者幀代替被調(diào)用者幀來(lái)處理返回和拋出異常。盡管該方法中的單個(gè)掛起對(duì)于深度 d的棧將花費(fèi)0(d),但由于每一幀僅被復(fù)制到堆一次,因此該方法的總分?jǐn)偝杀緸?(m),其 中m是曾掛起的幀數(shù)。m通常小于被調(diào)用的總幀數(shù)η。圖1示出根據(jù)本文所公開(kāi)主題的各方面用于在線性棧上高效恢復(fù)協(xié)同例程的系 統(tǒng)100的示例。系統(tǒng)100的所有或部分可駐留在諸如以下參照?qǐng)D3描述的計(jì)算機(jī)之類(lèi)的一 個(gè)或多個(gè)計(jì)算機(jī)上。系統(tǒng)100的所有或部分可駐留在諸如以下參照?qǐng)D4描述的計(jì)算機(jī)之類(lèi) 的一個(gè)或多個(gè)軟件開(kāi)發(fā)計(jì)算機(jī)(例如,計(jì)算機(jī)102)上。系統(tǒng)100或其部分可包括諸如以下 參照?qǐng)D4描述和示出的集成開(kāi)發(fā)環(huán)境(例如,IDE 104)的一部分?;蛘?,系統(tǒng)100或其部 分可被提供作為獨(dú)立系統(tǒng)或作為插件或附件。系統(tǒng)100可包括以下各項(xiàng)中的一個(gè)或多個(gè)處理器(諸如處理器142)、存儲(chǔ)器 144、和用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106。本領(lǐng)域公知的其他組件也可被包括 但不在這里示出。將理解,用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106可被加載到存儲(chǔ) 器144中以使得諸如處理器142之類(lèi)的一個(gè)或多個(gè)處理器執(zhí)行歸因于用于在線性棧上高效 恢復(fù)協(xié)同例程的模塊106的動(dòng)作。根據(jù)本文所公開(kāi)主題的各方面,用于在線性棧上高效恢 復(fù)協(xié)同例程的模塊106可接收或生成關(guān)于協(xié)同例程的掛起或恢復(fù)的通知。當(dāng)協(xié)同例程最初 被另一協(xié)同例程調(diào)用時(shí),被調(diào)用的協(xié)同例程的棧幀被放到棧上調(diào)用者的幀之上。若協(xié)同例 程未曾被掛起,則與該協(xié)同例程相關(guān)聯(lián)的幀不被復(fù)制到堆。若協(xié)同例程被掛起,則在首次掛 起時(shí),與被掛起協(xié)同例程相關(guān)聯(lián)的所有棧幀向下直至驅(qū)動(dòng)程序棧幀并且包括驅(qū)動(dòng)程序棧幀 被復(fù)制到堆。然而,后續(xù)掛起不導(dǎo)致先前被復(fù)制的棧幀被再次復(fù)制到堆。當(dāng)協(xié)同例程恢復(fù) 時(shí),驅(qū)動(dòng)程序例程僅將葉例程放到棧上。返回和拋出異常通過(guò)在棧上用調(diào)用者幀代替被調(diào) 用者幀來(lái)處理。用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106可包括以下各項(xiàng)中的一個(gè)或多個(gè) 編譯器114,諸如后臺(tái)編譯器、并行編譯器或增量編譯器;解析器,諸如后臺(tái)解析器、并行解 析器或增量解析器;或者插件、預(yù)處理器、或附件;或者對(duì)IDE、解析器、編譯器或預(yù)處理器 的擴(kuò)展。用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106可被附連到以下各項(xiàng)、合并到以 下各項(xiàng)內(nèi)或與以下各項(xiàng)相關(guān)聯(lián)編譯器,諸如后臺(tái)編譯器、并行編譯器或增量編譯器;解析器,諸如后臺(tái)解析器、并行解析器或增量解析器;或者插件、預(yù)處理器、或附件;或者對(duì)IDE、 解析器、編譯器或預(yù)處理器的擴(kuò)展。調(diào)用者110可代表程序、子例程或調(diào)用方協(xié)同例程。被調(diào)用者112可代表被調(diào)用 的協(xié)同例程、程序或子例程。用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106可監(jiān)視調(diào)用者 110與被調(diào)用者112之間的調(diào)用。用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106可執(zhí)行處 理以在利用單個(gè)線性機(jī)器調(diào)用棧的計(jì)算機(jī)環(huán)境中掛起和恢復(fù)協(xié)同例程,該單個(gè)線性機(jī)器調(diào) 用棧本身固有地不能掛起和恢復(fù)協(xié)同例程。用于在線性棧上高效恢復(fù)協(xié)同例程的模塊106 可監(jiān)視協(xié)同例程處理。僅響應(yīng)于檢測(cè)到協(xié)同例程(例如,被調(diào)用的協(xié)同例程)的首次掛起, 單個(gè)線性機(jī)器調(diào)用棧的能恢復(fù)部分被保存到分開(kāi)的數(shù)據(jù)結(jié)構(gòu)(諸如堆)中。協(xié)同例程被首 次掛起時(shí),其所有棧幀向下直至驅(qū)動(dòng)程序棧幀并且包括驅(qū)動(dòng)程序棧幀被復(fù)制到堆。然而,若 協(xié)同例程被再次掛起,則其棧幀不被再次復(fù)制到堆中。用于調(diào)用方協(xié)同例程和被調(diào)用協(xié)同 例程的該單個(gè)線性機(jī)器調(diào)用棧的能恢復(fù)部分可包括包含調(diào)用者的返回地址的棧幀、包含被 調(diào)用協(xié)同例程的返回地址的棧幀以及驅(qū)動(dòng)程序例程的棧幀。在遞歸協(xié)同例程調(diào)用鏈的情形中,線性機(jī)器調(diào)用棧的能恢復(fù)部分可包括包含到深 度d的所有被遞歸調(diào)用的協(xié)同例程的所有返回地址的所有棧幀。單個(gè)線性機(jī)器調(diào)用棧的能 恢復(fù)部分可被保存到諸如但不限于堆數(shù)據(jù)結(jié)構(gòu)之類(lèi)的數(shù)據(jù)結(jié)構(gòu)中。來(lái)自線性機(jī)器調(diào)用棧的 棧幀被保存到其中的數(shù)據(jù)結(jié)構(gòu)可與該線性機(jī)器調(diào)用棧分開(kāi)。在發(fā)生掛起時(shí),線性機(jī)器調(diào)用棧的能恢復(fù)部件或部分可被移除,并且恢復(fù)器棧幀 (包括恢復(fù)器的返回地址)可被復(fù)制到線性機(jī)器調(diào)用棧上,以使得當(dāng)協(xié)同例程恢復(fù)并且控 制返回到調(diào)用棧上的最頂部棧幀時(shí),控制被傳遞到恢復(fù)器108。當(dāng)被調(diào)用的協(xié)同例程恢復(fù) 時(shí),只有包括被調(diào)用協(xié)同例程的返回地址的棧幀才能被復(fù)制到該單個(gè)線性機(jī)器調(diào)用棧上, 而不將所有被保存的能恢復(fù)部分都重構(gòu)到該單個(gè)線性機(jī)器調(diào)用棧上。響應(yīng)于檢測(cè)到暫停協(xié) 同例程(例如,被調(diào)用的協(xié)同例程)的恢復(fù),線性機(jī)器調(diào)用棧上的恢復(fù)器棧幀可被處理并且 恢復(fù)器108可被調(diào)用。響應(yīng)于檢測(cè)到被調(diào)用協(xié)同例程的恢復(fù),被調(diào)用協(xié)同例程可被執(zhí)行,從 而通過(guò)將控制返回到放在該單個(gè)線性機(jī)器調(diào)用棧上的關(guān)于恢復(fù)器的返回地址來(lái)將控制返 回給恢復(fù)器。恢復(fù)器108可通過(guò)將調(diào)用者的棧幀復(fù)制到調(diào)用棧上來(lái)將控制返回到關(guān)于調(diào)用 者的棧幀中的返回地址。即,在協(xié)同例程恢復(fù)時(shí),恢復(fù)器108可僅為合適協(xié)同例程將最頂部 葉幀復(fù)制到調(diào)用棧,而不重構(gòu)整個(gè)調(diào)用棧。該過(guò)程可繼續(xù),直至整個(gè)調(diào)用鏈已完成。當(dāng)協(xié)同 例程返回其調(diào)用者時(shí),被調(diào)用者棧幀被調(diào)用者棧幀代替。在拋出異常時(shí),根據(jù)本文所公開(kāi)主題的各方面,可抓住該異常,被調(diào)用者的棧幀可 被調(diào)用者的棧幀代替,并且隨后可重新拋出該異常。圖2示出根據(jù)本文所公開(kāi)主題的各方面用于在線性棧上高效恢復(fù)協(xié)同例程的方 法200的示例。在202,協(xié)同例程(調(diào)用者)調(diào)用另一協(xié)同例程(被調(diào)用者)。在204,若被 調(diào)用協(xié)同例程從未掛起,則棧不被復(fù)制到堆006)。即,被調(diào)用例程的幀被放在棧上調(diào)用者 的幀之上并且通過(guò)傳統(tǒng)的機(jī)器調(diào)用棧處理來(lái)處理。在204,若發(fā)生被調(diào)用協(xié)同例程的掛起, 則在208,機(jī)器棧的能恢復(fù)部分若先前尚未被復(fù)制到堆則被復(fù)制到堆上。被調(diào)用者首次被掛 起時(shí),與被掛起協(xié)同例程相關(guān)聯(lián)的所有棧幀向下直至驅(qū)動(dòng)程序棧幀并且包括驅(qū)動(dòng)程序棧幀 被復(fù)制到堆。然而,后續(xù)掛起不導(dǎo)致先前被復(fù)制的棧幀被再次復(fù)制到堆。恢復(fù)器棧幀被壓 到調(diào)用棧上?;謴?fù)器調(diào)用棧在被處理時(shí)將控制返回到恢復(fù)器而非返回到調(diào)用者。當(dāng)或若被調(diào)用者在210恢復(fù)時(shí),恢復(fù)器在212被調(diào)用,并且恢復(fù)器在212僅將被調(diào)用者的葉幀(最頂 部棧幀)從堆重構(gòu)到棧上并且處理繼續(xù)。在214,若拋出異常或者若被調(diào)用者返回,則棧上 的被調(diào)用者幀被調(diào)用者棧幀代替并且處理繼續(xù)。例如,假設(shè)協(xié)同例程實(shí)現(xiàn)按需產(chǎn)生集合結(jié)果的迭代器。該集合可由二進(jìn)制樹(shù)數(shù)據(jù) 結(jié)構(gòu)表示,其中該二進(jìn)制樹(shù)中的每個(gè)節(jié)點(diǎn)包括包含該集合的成員的值。為了以二進(jìn)制樹(shù)規(guī) 定的指定次序產(chǎn)生該集合的元素,該二進(jìn)制樹(shù)可通過(guò)協(xié)同例程的遞歸調(diào)用來(lái)遍歷。例如,假 設(shè)二進(jìn)制樹(shù)表示元素1、2和3的集合。為了以該順序產(chǎn)生元素1、2、3,二進(jìn)制樹(shù)的根節(jié)點(diǎn)通 ??删哂兄?,根節(jié)點(diǎn)的左孩子節(jié)點(diǎn)可具有值1且沒(méi)有左或右子樹(shù),而根節(jié)點(diǎn)的右孩子節(jié)點(diǎn) 可具有值3且沒(méi)有左或右子樹(shù)。迭代器首先產(chǎn)生根節(jié)點(diǎn)的左樹(shù)的值,隨后從根節(jié)點(diǎn)產(chǎn)生值, 然后產(chǎn)生右樹(shù)的元素。該過(guò)程利用遞歸協(xié)同例程。在產(chǎn)生了每個(gè)元素之后,協(xié)同例程暫停, 直至該集合的下一元素被請(qǐng)求。當(dāng)調(diào)用方例程在二進(jìn)制樹(shù)上調(diào)用迭代器函數(shù)時(shí),調(diào)用者的地址進(jìn)棧。迭代器在二 進(jìn)制樹(shù)的根上調(diào)用第一協(xié)同例程。第一協(xié)同例程的下一指令的地址被放在棧上。向根節(jié)點(diǎn) 的左樹(shù)作出第二遞歸協(xié)同例程調(diào)用。在根節(jié)點(diǎn)的左樹(shù)上調(diào)用的第二協(xié)同例程的地址被放在 棧上。由于根節(jié)點(diǎn)的左樹(shù)沒(méi)有子樹(shù),因此不向左樹(shù)的左孩子節(jié)點(diǎn)作出遞歸調(diào)用。產(chǎn)生存儲(chǔ) 在左樹(shù)中的該集合的元素(1)。在左節(jié)點(diǎn)上調(diào)用的協(xié)同例程掛起。在根上的協(xié)同例程也掛 起。當(dāng)樹(shù)的左孩子節(jié)點(diǎn)上的協(xié)同例程掛起時(shí),有2幀(在左根上調(diào)用的協(xié)同例程和在 根上調(diào)用的協(xié)同例程的地址)的調(diào)用棧被保存在堆中?;謴?fù)器幀被復(fù)制到棧上。當(dāng)協(xié)同例 程由于要求該集合的元素的客戶機(jī)要求下一元素而恢復(fù)時(shí),并非從堆取出兩個(gè)所保存幀并 將它們放回到棧上,而是僅將與左樹(shù)上(其中有1的節(jié)點(diǎn)上)的協(xié)同例程調(diào)用相對(duì)應(yīng)的最 頂部幀復(fù)制到棧中。因此,棧上有一幀,其中棧上的該幀對(duì)應(yīng)于在左節(jié)點(diǎn)上被調(diào)用的協(xié)同例 程。第二調(diào)用確定其中有1的節(jié)點(diǎn)沒(méi)有右樹(shù)。結(jié)果將被返回到的協(xié)同例程是在根節(jié)點(diǎn)上調(diào)用的協(xié)同例程,但該幀沒(méi)有被復(fù)制回 棧上,因此并非如傳統(tǒng)模型中那樣執(zhí)行棧返回,而是協(xié)同例程返回到恢復(fù)器幀(其為棧上 的下一幀)上的地址。因此,恢復(fù)通過(guò)恢復(fù)器例程來(lái)引導(dǎo)?;謴?fù)器確定根的返回地址并引 導(dǎo)將結(jié)果返回該地址。在根節(jié)點(diǎn)上調(diào)用的協(xié)同例程產(chǎn)生其值( 并再次掛起??蛻魴C(jī)下次 要求值時(shí),恢復(fù)器被再次調(diào)用。恢復(fù)器將根幀放在棧上,因?yàn)檫@是自先前開(kāi)始就掛起的幀。 在根節(jié)點(diǎn)上調(diào)用的協(xié)同例程從其產(chǎn)生其自己的值之后的指令開(kāi)始運(yùn)行。接下來(lái),在右分支 上作出傳統(tǒng)的遞歸協(xié)同例程調(diào)用以產(chǎn)生右子樹(shù)中的任何值。此時(shí),調(diào)用棧上有三幀底部為恢復(fù)器幀,其上是關(guān)于在根上調(diào)用的協(xié)同例程的 幀,頂部是關(guān)于在右葉上調(diào)用的協(xié)同例程的幀。右葉確定其沒(méi)有左分支,且將產(chǎn)生其自己的 值(3)并且掛起。在掛起時(shí),最頂部的兩幀被存儲(chǔ)在堆中并且恢復(fù)器幀被復(fù)制到棧上。當(dāng) 客戶機(jī)要求另一元素時(shí),發(fā)生恢復(fù)。最頂部的幀引導(dǎo)至恢復(fù)器的處理。恢復(fù)器將與右葉相 對(duì)應(yīng)的幀放在棧上。在右葉上調(diào)用的協(xié)同例程確定其沒(méi)有右子樹(shù)。其將結(jié)果返回給恢復(fù) 器,表明其完成?;謴?fù)器將根幀放在棧上。根上的協(xié)同例程恢復(fù)。它確定其完成并且返回 到驅(qū)動(dòng)程序。棧上的下一幀是調(diào)用者的返回地址。調(diào)用者接收關(guān)于集合中沒(méi)有更多元素的 消息。將理解,以上描述的方法可通過(guò)向恢復(fù)器產(chǎn)生關(guān)于接下來(lái)運(yùn)行哪個(gè)協(xié)同例程的指令來(lái)應(yīng)用于具有多個(gè)入口點(diǎn)的協(xié)同例程。還將理解,以上描述的過(guò)程可提供對(duì)異步編程的 支持。例如,假設(shè)異步例程按節(jié)讀取文件。該例程可在循環(huán)中執(zhí)行,從而遞歸地調(diào)用讀取文 件的一部分的另一例程。為了避免使線程總是在運(yùn)行,主例程可被掛起直至讀取文件的一 部分的協(xié)同例程結(jié)束。掛起的主例程可在讀取文件的一部分的協(xié)同例程返回結(jié)果時(shí)恢復(fù)。 異步主例程和讀取文件的一部分的協(xié)同例程兩者被掛起直至文件的一部分返回。帶回文件 內(nèi)容的線程恢復(fù)請(qǐng)求信息的例程,將文件內(nèi)容給它并且它將內(nèi)容傳回給主例程。該過(guò)程被重復(fù),從而文件的另一節(jié)被另一遞歸調(diào)用檢索,依此類(lèi)推。在這種情形 中,通過(guò)從文件帶回內(nèi)容的操作系統(tǒng)事件來(lái)發(fā)起恢復(fù)。在這種情形中,當(dāng)操作系統(tǒng)帶回文 件內(nèi)容時(shí),其執(zhí)行對(duì)早先安裝在棧中的恢復(fù)器的回調(diào)?;謴?fù)器通過(guò)回到棧上的最新葉例程 (讀取文件的節(jié)的例程)并從其所到的地方執(zhí)行它來(lái)如上所述地恢復(fù)協(xié)同例程。當(dāng)葉例程 完成時(shí),其返回到恢復(fù)器并且恢復(fù)器返回到原始調(diào)用者。執(zhí)行繼續(xù),直至文件的下一節(jié)被請(qǐng) 求,此時(shí)被調(diào)用例程和調(diào)用方例程被再次掛起,依此類(lèi)推。合適計(jì)算環(huán)境的示例為了提供有關(guān)本文所公開(kāi)的主題的各個(gè)方面的上下文,圖3以及以下討論旨在提 供其中可以實(shí)現(xiàn)各實(shí)施例的合適計(jì)算環(huán)境510的簡(jiǎn)要概括描述。盡管本文所公開(kāi)的主題是 在諸如程序模塊等由一個(gè)或多個(gè)計(jì)算機(jī)或其它計(jì)算設(shè)備執(zhí)行的計(jì)算機(jī)可執(zhí)行指令的通用 上下文中描述的,但本領(lǐng)域技術(shù)人員將認(rèn)識(shí)到,本文所公開(kāi)的主題的各部分還能夠結(jié)合其 它程序模塊和/或硬件和軟件的組合來(lái)實(shí)現(xiàn)。通常,程序模塊包括執(zhí)行特定任務(wù)或?qū)崿F(xiàn)特 定數(shù)據(jù)類(lèi)型的例程、程序、對(duì)象、物理人為產(chǎn)物、數(shù)據(jù)結(jié)構(gòu)等。通常,程序模塊的功能可以在 各個(gè)實(shí)施例中按需進(jìn)行組合或分布。計(jì)算環(huán)境510只是合適的操作環(huán)境的一個(gè)示例,并且 不旨在對(duì)此處所公開(kāi)的主題的使用范圍或功能提出任何限制。參照?qǐng)D3,描述了計(jì)算機(jī)512形式的用于線性棧上高效恢復(fù)協(xié)同例程的計(jì)算設(shè)備。 計(jì)算機(jī)512可包括處理單元514、系統(tǒng)存儲(chǔ)器516和系統(tǒng)總線518。處理單元514可以是各 種可用處理器中的任何一種。也可以使用雙微處理器及其他多處理器體系結(jié)構(gòu)作為處理單 元514。系統(tǒng)存儲(chǔ)器516可包括易失性存儲(chǔ)器520和非易失性存儲(chǔ)器522。非易失性存儲(chǔ) 器522可包括只讀存儲(chǔ)器(ROM)、可編程ROM(PROM)、電可編程ROM(EPROM)或閃存。易失性 存儲(chǔ)器520可包括可充當(dāng)外部高速緩沖存儲(chǔ)器的隨機(jī)存取存儲(chǔ)器(RAM)。系統(tǒng)總線518將 系統(tǒng)物理人為產(chǎn)物(包括系統(tǒng)存儲(chǔ)器516)耦合到處理單元514。系統(tǒng)總線518可以是幾種 類(lèi)型的總線結(jié)構(gòu)中的任何一種,包括存儲(chǔ)器總線、存儲(chǔ)控制器、外圍總線、外部總線或局部 總線,并且可以使用各種可用總線體系結(jié)構(gòu)中的任一種。計(jì)算機(jī)512通常包括各種計(jì)算機(jī)可讀介質(zhì),諸如易失性和非易失性介質(zhì)、可移動(dòng) 和不可移動(dòng)介質(zhì)。計(jì)算機(jī)存儲(chǔ)介質(zhì)可以通過(guò)用于存儲(chǔ)諸如計(jì)算機(jī)可讀指令、數(shù)據(jù)結(jié)構(gòu)、程 序模塊或其它數(shù)據(jù)等信息的任何方法或技術(shù)來(lái)實(shí)現(xiàn)。計(jì)算機(jī)存儲(chǔ)介質(zhì)包括但不限于,RAM、 ROM、EEPR0M、閃存或其它存儲(chǔ)器技術(shù)、CDR0M、數(shù)字多功能盤(pán)(DVD)或其它光盤(pán)存儲(chǔ)、磁盒、 磁帶、磁盤(pán)存儲(chǔ)或其它磁存儲(chǔ)設(shè)備、或可以用來(lái)儲(chǔ)存所期望的信息并可由計(jì)算機(jī)512訪問(wèn) 的任何其他非瞬態(tài)介質(zhì)。將理解,圖3描述了可充當(dāng)用戶與計(jì)算機(jī)資源之間的媒介的軟件。該軟件可以包 括可存儲(chǔ)在盤(pán)存儲(chǔ)5M上的操作系統(tǒng)528,該操作系統(tǒng)可控制并分配計(jì)算機(jī)系統(tǒng)512的資 源。盤(pán)存儲(chǔ)5M可以是通過(guò)諸如接口 5 的不可移動(dòng)存儲(chǔ)器接口連接到系統(tǒng)總線518的硬盤(pán)驅(qū)動(dòng)器。系統(tǒng)應(yīng)用程序530利用由操作系統(tǒng)5 通過(guò)存儲(chǔ)在系統(tǒng)存儲(chǔ)器516中或者存儲(chǔ) 在盤(pán)存儲(chǔ)5M上的程序模塊532和程序數(shù)據(jù)534對(duì)資源的管理。應(yīng)該明白,計(jì)算機(jī)可用各 種操作系統(tǒng)或操作系統(tǒng)的組合來(lái)實(shí)現(xiàn)。用戶可通過(guò)輸入設(shè)備536向計(jì)算機(jī)512輸入命令或信息。輸入設(shè)備536包括但不 限于定點(diǎn)設(shè)備,諸如鼠標(biāo)、跟蹤球、指示筆、觸摸墊、鍵盤(pán)、話筒等。這些及其他輸入設(shè)備通過(guò) 系統(tǒng)總線518經(jīng)由接口端口 538連接到處理單元514。接口端口 538可表示串行端口、并行 端口、通用串行總線(USB)等。輸出設(shè)備540可與輸入設(shè)備使用相同類(lèi)型的端口。提供輸 出適配器M2以舉例說(shuō)明存在像監(jiān)視器、揚(yáng)聲器、以及打印機(jī)的需要特定適配器的一些輸 出裝置M0。輸出適配器542包括但不限于,在輸出設(shè)備540和系統(tǒng)總線518之間提供連接 的視頻卡和聲卡。其他設(shè)備和/或設(shè)備系統(tǒng),諸如遠(yuǎn)程計(jì)算機(jī)M4,可提供輸入和輸出兩種 能力。計(jì)算機(jī)512可以使用到諸如遠(yuǎn)程計(jì)算機(jī)544之類(lèi)的一個(gè)或多個(gè)遠(yuǎn)程計(jì)算機(jī)的邏輯 連接來(lái)在聯(lián)網(wǎng)環(huán)境中操作。遠(yuǎn)程計(jì)算機(jī)544可以是個(gè)人計(jì)算機(jī)、服務(wù)器、路由器、網(wǎng)絡(luò)PC、對(duì) 等設(shè)備或其它常見(jiàn)的網(wǎng)絡(luò)節(jié)點(diǎn),并且通常包括許多或所有以上相對(duì)于計(jì)算機(jī)512所描述的 元件,盡管在圖4中僅示出了存儲(chǔ)器存儲(chǔ)設(shè)備M6。遠(yuǎn)程計(jì)算機(jī)544可經(jīng)由通信連接550邏 輯地連接。網(wǎng)絡(luò)接口 548涵蓋諸如局域網(wǎng)(LAN)和廣域網(wǎng)(WAN)這樣的通信網(wǎng)絡(luò),但也可 包括其他網(wǎng)絡(luò)。通信連接550是指用來(lái)將網(wǎng)絡(luò)接口 548連接到總線518的硬件/軟件。連 接550可以在計(jì)算機(jī)512內(nèi)部或外部并且包括諸如調(diào)制解調(diào)器(電話、電纜、DSL和無(wú)線) 和ISDN適配器、以太網(wǎng)卡等內(nèi)部和外部技術(shù)。應(yīng)該理解,所示網(wǎng)絡(luò)連接僅是示例,并且可以使用在計(jì)算機(jī)之間建立通信鏈路的 其它手段。本領(lǐng)域的普通技術(shù)人員可以理解,計(jì)算機(jī)512或其它客戶機(jī)設(shè)備可作為計(jì)算機(jī) 網(wǎng)絡(luò)的一部分來(lái)部署。在這一點(diǎn)上,本文所公開(kāi)的主題涉及具有任意數(shù)量的存儲(chǔ)器或存儲(chǔ) 單元以及在任意數(shù)量的存儲(chǔ)單元或卷上發(fā)生的任意數(shù)量的應(yīng)用程序和進(jìn)程的任何計(jì)算機(jī) 系統(tǒng)。本文所公開(kāi)的主題的各方面可應(yīng)用于具有部署在網(wǎng)絡(luò)環(huán)境中的具有遠(yuǎn)程或本地存儲(chǔ) 的服務(wù)器計(jì)算機(jī)和客戶計(jì)算機(jī)的環(huán)境。本文所公開(kāi)的主題的各方面也可應(yīng)用于具有編程語(yǔ) 言功能、解釋和執(zhí)行能力的獨(dú)立計(jì)算設(shè)備。圖4示出集成開(kāi)發(fā)環(huán)境(IDE) 600和通用語(yǔ)言運(yùn)行時(shí)環(huán)境602。IDE 600可允許用 戶(例如,開(kāi)發(fā)者、程序員、設(shè)計(jì)者、編碼者等)在計(jì)算機(jī)系統(tǒng)中設(shè)計(jì)、編碼、編譯、測(cè)試、運(yùn) 行、編輯、調(diào)試或構(gòu)建程序、程序集、網(wǎng)站、web應(yīng)用程序和web服務(wù)。軟件程序可包括以一種 或多種源代碼語(yǔ)言(例如,VisualBasic、Visual J#、C++、C#、J#、Java Script,APL,COBOL, Pascal、Eiffel、Haskell、ML、Oberon> Perl、Python、Scheme、Smalltalk 等)創(chuàng)建的源代 碼(組件610)。IDE 600可提供本機(jī)代碼開(kāi)發(fā)環(huán)境,或者可提供在虛擬機(jī)上運(yùn)行的托管代 碼開(kāi)發(fā),或者可提供其組合。IDE 600可提供使用.NET框架的托管代碼開(kāi)發(fā)環(huán)境。可使用 語(yǔ)言專(zhuān)用源編譯器620從源代碼組件610和本機(jī)代碼組件611創(chuàng)建中間語(yǔ)言組件650,并且 在執(zhí)行應(yīng)用時(shí)使用中間語(yǔ)言編譯器660(例如,即時(shí)(JIT)編譯器)從中間語(yǔ)言組件650創(chuàng) 建本機(jī)代碼組件611(例如,機(jī)器可執(zhí)行指令)。即,當(dāng)IL應(yīng)用被執(zhí)行時(shí),其在被執(zhí)行的同時(shí) 被編譯成適合正在其上執(zhí)行它的平臺(tái)的合適機(jī)器語(yǔ)言,藉此使代碼能跨若干平臺(tái)便攜。或 者,在其他實(shí)施例中,程序可被編譯成適合其目標(biāo)平臺(tái)的本機(jī)代碼機(jī)器語(yǔ)言(未示出)。用戶可根據(jù)已知軟件編程技術(shù)以及與特定源語(yǔ)言相關(guān)聯(lián)的特定邏輯和句法規(guī)則經(jīng)由IDE 600中的用戶接口 640和源代碼編輯器651來(lái)創(chuàng)建和/或編輯源代碼組件。此后, 源代碼組件610可經(jīng)由源編譯器620被編譯,藉此可創(chuàng)建該程序的中間語(yǔ)言表示,諸如匯編 630。匯編630可包括中間語(yǔ)言組件650和元數(shù)據(jù)642。應(yīng)用程序設(shè)計(jì)可以能夠在部署前被 驗(yàn)證。此處所述的各種技術(shù)可結(jié)合硬件或軟件,或在適當(dāng)時(shí)以其組合來(lái)實(shí)現(xiàn)。由此,本文 所公開(kāi)的方法和裝置或其特定方面或部分可采取包含在諸如軟盤(pán)、CD-ROM、硬盤(pán)驅(qū)動(dòng)器或 任何其它機(jī)器可讀存儲(chǔ)介質(zhì)等有形介質(zhì)中的程序代碼(即,指令)的形式,其中當(dāng)程序代碼 被加載到諸如計(jì)算機(jī)等機(jī)器內(nèi)并由其執(zhí)行時(shí),該機(jī)器成為用于實(shí)現(xiàn)本文所公開(kāi)的主題的各 方面的裝置。在程序代碼在可編程計(jì)算機(jī)上執(zhí)行的情況下,計(jì)算設(shè)備通常將包括處理器、該 處理器可讀的存儲(chǔ)介質(zhì)(包括易失性和非易失性的存儲(chǔ)器和/或存儲(chǔ)元件)、至少一個(gè)輸入 設(shè)備、以及至少一個(gè)輸出設(shè)備??衫缤ㄟ^(guò)使用數(shù)據(jù)處理API等來(lái)利用域?qū)S镁幊棠P透?方面的創(chuàng)建和/或?qū)崿F(xiàn)的一個(gè)或多個(gè)程序可用高級(jí)過(guò)程語(yǔ)言或面向?qū)ο蟮木幊陶Z(yǔ)言來(lái)實(shí) 現(xiàn)以與計(jì)算機(jī)系統(tǒng)通信。然而,如果需要,該程序可以用匯編語(yǔ)言或機(jī)器語(yǔ)言來(lái)實(shí)現(xiàn)。在任 何情形中,語(yǔ)言可以是編譯語(yǔ)言或解釋語(yǔ)言,且與硬件實(shí)現(xiàn)相結(jié)合。雖然已結(jié)合附圖描述了本文所公開(kāi)的主題,但是應(yīng)理解,可作出修改以按不同方 式執(zhí)行相同功能。
權(quán)利要求
1.一種系統(tǒng)(100),包括處理器(14 和存儲(chǔ)器(144),所述存儲(chǔ)器包括配置成使所述處理器(14 執(zhí)行以下動(dòng) 作的模塊(106)在利用固有地不能掛起和恢復(fù)協(xié)同例程的單個(gè)線性機(jī)器調(diào)用棧的計(jì)算機(jī)環(huán)境中掛起 和恢復(fù)包括調(diào)用方協(xié)同例程(110)和被調(diào)用協(xié)同例程(112)的協(xié)同例程,其中僅響應(yīng)于檢測(cè)到所述被調(diào)用協(xié)同例程的掛起,所述模塊保存先前未保存的所述單個(gè)線性機(jī)器調(diào)用棧的能恢復(fù)部分,所述單個(gè)線性機(jī)器調(diào)用棧 的所述能恢復(fù)部分包括所述調(diào)用方協(xié)同例程的棧幀、所述被調(diào)用協(xié)同例程的棧幀以及恢復(fù) 器的棧幀;將所述單個(gè)線性機(jī)器調(diào)用棧的所述能恢復(fù)部分從所述單個(gè)線性機(jī)器調(diào)用棧移除;將恢復(fù)器的返回地址放到所述單個(gè)線性機(jī)器調(diào)用棧上;以及響應(yīng)于檢測(cè)到所述被調(diào)用 協(xié)同例程的恢復(fù)僅將所述被調(diào)用協(xié)同例程的所述棧幀復(fù)制到所述單個(gè)線性機(jī)器調(diào)用棧上,而不將所述 單個(gè)線性機(jī)器調(diào)用棧的所有所述能恢復(fù)部分復(fù)制到所述單個(gè)線性機(jī)器調(diào)用棧上。
2.如權(quán)利要求1所述的系統(tǒng),其特征在于,響應(yīng)于檢測(cè)到所述被調(diào)用協(xié)同例程的恢復(fù), 通過(guò)將控制返回到放在所述單個(gè)線性機(jī)器調(diào)用棧上的所述恢復(fù)器的所述返回地址來(lái)將控 制返回給所述恢復(fù)器,所述恢復(fù)器將所述被調(diào)用協(xié)同例程的所述棧幀放到所述單個(gè)線性機(jī) 器調(diào)用棧上。
3.如權(quán)利要求1所述的系統(tǒng),其特征在于,響應(yīng)于拋出異常,在所述單個(gè)線性機(jī)器調(diào)用 棧上所述被調(diào)用協(xié)同例程的所述棧幀被所述調(diào)用方協(xié)同例程的所述棧幀代替。
4.如權(quán)利要求1所述的系統(tǒng),其特征在于,通過(guò)所述調(diào)用方協(xié)同例程請(qǐng)求附加信息來(lái) 發(fā)起恢復(fù)。
5.如權(quán)利要求1所述的系統(tǒng),其特征在于,通過(guò)返回所述調(diào)用方協(xié)同例程所請(qǐng)求的信 息來(lái)發(fā)起恢復(fù)。
6.一種方法000),包括在其中實(shí)現(xiàn)線性機(jī)器調(diào)用棧的軟件開(kāi)發(fā)計(jì)算機(jī)上執(zhí)行的編程環(huán)境中,其中所述線性機(jī) 器調(diào)用棧固有地不能掛起和恢復(fù)協(xié)同例程響應(yīng)于接收到從調(diào)用者對(duì)被調(diào)用協(xié)同例程的未掛起協(xié)同例程調(diào)用,不將與所述被調(diào)用 協(xié)同例程相關(guān)聯(lián)的棧幀從所述線性機(jī)器調(diào)用棧保存到堆O06);以及僅響應(yīng)于檢測(cè)到從所述調(diào)用者調(diào)用的被調(diào)用協(xié)同例程的首次掛起,將與所述被調(diào)用協(xié) 同例程相關(guān)聯(lián)的棧幀從所述線性機(jī)器調(diào)用棧保存到堆(208)。
7.如權(quán)利要求6所述的方法,其特征在于,還包括響應(yīng)于檢測(cè)到所述被調(diào)用協(xié)同例程的恢復(fù),從所述堆向所述線性機(jī)器棧重構(gòu)僅葉幀。
8.如權(quán)利要求6所述的方法,其特征在于,還包括實(shí)現(xiàn)高級(jí)編程語(yǔ)言的迭代器或?qū)崿F(xiàn)異步編程。
9.如權(quán)利要求6所述的方法,其特征在于,還包括響應(yīng)于所述被調(diào)用協(xié)同例程返回,用所述調(diào)用者的棧幀來(lái)代替所述線性機(jī)器調(diào)用棧上 所述被調(diào)用協(xié)同例程的所述棧幀。
10.如權(quán)利要求6所述的方法,其特征在于,還包括響應(yīng)于拋出異常,抓住所述異常,在所述線性機(jī)器調(diào)用棧上用所述調(diào)用者的棧幀來(lái)代 替所述被調(diào)用協(xié)同例程的所述棧幀并重新拋出所述異常。
11.一種包括計(jì)算機(jī)可執(zhí)行指令的計(jì)算機(jī)可讀存儲(chǔ)介質(zhì),所述指令在被執(zhí)行時(shí)使至少 一個(gè)處理器(142)執(zhí)行對(duì)未掛起協(xié)同例程的線性機(jī)器調(diào)用棧處理;除所述線性機(jī)器調(diào)用棧處理以外,通過(guò)以下操作對(duì)被掛起協(xié)同例程執(zhí)行調(diào)用棧處理 將包括所述被掛起協(xié)同例程的返回地址的棧幀、包括所述調(diào)用者的返回地址的棧幀以 及驅(qū)動(dòng)程序例程的棧幀保存到與所述線性機(jī)器調(diào)用棧分開(kāi)的數(shù)據(jù)結(jié)構(gòu)中; 掛起所述調(diào)用者;從所述線性機(jī)器調(diào)用棧移除所述調(diào)用者的所述棧幀和所述被掛起協(xié)同例程的所述棧幀;將恢復(fù)器的返回地址放到所述線性機(jī)器調(diào)用棧上;以及響應(yīng)于接收到所述被掛起協(xié)同 例程的恢復(fù)將所述調(diào)用者的所述棧幀復(fù)制到所述線性機(jī)器調(diào)用棧上。
12.如權(quán)利要求11所述的計(jì)算機(jī)可讀存儲(chǔ)介質(zhì),其特征在于,還包括在被執(zhí)行時(shí)使所 述至少一個(gè)處理器執(zhí)行以下動(dòng)作的計(jì)算機(jī)可執(zhí)行指令恢復(fù)所述被掛起協(xié)同例程,其中所恢復(fù)的協(xié)同例程返回到所述恢復(fù)器,并且所述恢復(fù) 器將所述調(diào)用者的棧幀復(fù)制到所述線性機(jī)器調(diào)用棧上。
13.如權(quán)利要求11所述的計(jì)算機(jī)可讀存儲(chǔ)介質(zhì),其特征在于,還包括在被執(zhí)行時(shí)使所 述至少一個(gè)處理器執(zhí)行以下動(dòng)作的計(jì)算機(jī)可執(zhí)行指令支持異步編程。
14.如權(quán)利要求11所述的計(jì)算機(jī)可讀存儲(chǔ)介質(zhì),其特征在于,還包括在被執(zhí)行時(shí)使所 述至少一個(gè)處理器執(zhí)行以下動(dòng)作的計(jì)算機(jī)可執(zhí)行指令響應(yīng)于所述調(diào)用者請(qǐng)求附加信息,恢復(fù)所述被掛起協(xié)同例程。
15.如權(quán)利要求11所述的計(jì)算機(jī)可讀存儲(chǔ)介質(zhì),其特征在于,還包括在被執(zhí)行時(shí)使所 述至少一個(gè)處理器執(zhí)行以下動(dòng)作的計(jì)算機(jī)可執(zhí)行指令響應(yīng)于返回所請(qǐng)求的信息,恢復(fù)所述協(xié)同例程。
全文摘要
未掛起協(xié)同例程由機(jī)器調(diào)用棧機(jī)制來(lái)處理,其中該棧隨著作出遞歸調(diào)用和從遞歸調(diào)用返回而增長(zhǎng)和收縮。然而,在協(xié)同例程掛起時(shí),執(zhí)行附加的調(diào)用棧處理。發(fā)出掛起消息,并且調(diào)用棧的整個(gè)能恢復(fù)部分被移除并被復(fù)制到堆。將控制返回給驅(qū)動(dòng)程序方法(恢復(fù)器)的幀被復(fù)制到調(diào)用棧,從而協(xié)同例程的恢復(fù)不會(huì)遞歸地重新激活整個(gè)調(diào)用棧。相反,恢復(fù)器僅重新激活被稱(chēng)為葉幀的最頂部或最當(dāng)前幀。在協(xié)同例程掛起時(shí),其不返回到其調(diào)用者,而是返回到已重新激活它的恢復(fù)器。
文檔編號(hào)G06F9/48GK102141937SQ20111000847
公開(kāi)日2011年8月3日 申請(qǐng)日期2011年1月6日 優(yōu)先權(quán)日2010年1月7日
發(fā)明者H·J·M·梅杰, M·托格森, N·M·加夫特, N·古斯塔夫松 申請(qǐng)人:微軟公司