專利名稱:可恢復(fù)的方法
可恢復(fù)的方法
背景技術(shù):
多核處理器是一種包括兩個(gè)或更多單獨(dú)的處理器(核)的處理系統(tǒng)。眾核(many-core)處理器是一種如下的處理器在所述處理器中,核的數(shù)目大得足以使得傳統(tǒng)的多處理器編程技術(shù)不再為高效的。為眾核處理器開發(fā)軟件的程序員必須調(diào)整他們編寫他們的程序的方式。也就是說,為了為這些類型的計(jì)算環(huán)境編寫高效的程序,程序員必須編寫異步代碼、一種可以與其他代碼并發(fā)執(zhí)行而不對其產(chǎn)生干擾的代碼。在沒有語言支持的情況下編寫無阻塞異步代碼是困難的,因?yàn)槌绦騿T必須以連續(xù)傳遞樣式(continuation passing style, CPS)、例如通過使用基于回調(diào)的代碼來編寫代碼。在傳統(tǒng)同步編程中為隱式的事物在CPS編程中變?yōu)轱@式的。例如,在傳統(tǒng)編碼中,當(dāng)函數(shù)被調(diào)用時(shí),其返回某值。在CPS中,函數(shù)采取顯式連續(xù)變元(argument)、一種接收在原始函數(shù)內(nèi)執(zhí)行的計(jì)算的結(jié)果的函數(shù)。類似地,當(dāng)子例程在CPS 函數(shù)內(nèi)被調(diào)用時(shí),主調(diào)函數(shù)必須提供將用子例程返回值來調(diào)用的過程(procedure)。諸如例如C#之類的一些語言確實(shí)提供了某種形式的借助于迭代器構(gòu)造改寫的編譯器支持的連續(xù)傳遞。這種類型的語言支持對于遞歸而言以及對于異步編程所需的其他類型的編碼技術(shù)而言不是特別優(yōu)化的。概述盡管針對迭代器的內(nèi)建語言支持可以幫助解決與被惰性地評估的集合相關(guān)聯(lián)的一些問題,并且盡管在某些語言中在某種程度上不存在針對異步編程的內(nèi)建語言支持,但是在此所公開的主體針對一種統(tǒng)一方案,其抽象出這些領(lǐng)域的各個(gè)方面的特性并且提供通用的外部機(jī)制,所述外部機(jī)制可以解決與異步編程、通過迭代器惰性地生成集合、編寫對稱協(xié)同例程等等相關(guān)聯(lián)的大量問題。提供了 API (程序模塊),所述API處于編程語言的外部但是提供可插入到語言編譯器中的功能。所提供的API調(diào)節(jié)與使用通用基于模式的方案進(jìn)行的異步編程、迭代器或編寫對稱協(xié)同例程相關(guān)聯(lián)的功能。在API中提供了若干類型的可恢復(fù)方法,所述可恢復(fù)方法可以應(yīng)用于以傳統(tǒng)程序代碼編寫的方法主體。以傳統(tǒng)編程代碼編寫的方法主體中的在句法上可區(qū)分的控制點(diǎn)通過編譯器使用外部API來調(diào)用該代碼的變換。經(jīng)變換的代碼實(shí)現(xiàn)夾在經(jīng)變換的代碼的控制點(diǎn)之間的代碼的暫停和恢復(fù)。也就是說,里面具有控制點(diǎn)的代碼的本體(例如方法)中所包括的源代碼被變換為使得該方法內(nèi)的代碼可以在分立的部分中執(zhí)行,每個(gè)部分都在經(jīng)變換的代碼中的控制點(diǎn)處開始和結(jié)束。無論控制點(diǎn)位于代碼中的何處,該代碼都可以要么直接地、要么作為暫停的遞歸調(diào)用的一部分而暫停。該代碼可以從其暫停的點(diǎn)處恢復(fù)。不同類型的可恢復(fù)方法可以通過該方法在暫停后如何以及何時(shí)恢復(fù)、以及通過在代碼暫停、返回和終止以后來回流動(dòng)的變元和返回值的類型來區(qū)分。暫??刂泣c(diǎn)可以任選地向調(diào)用者返回值,并且可以使用yield(控制權(quán)轉(zhuǎn)移)表達(dá)式從恢復(fù)模塊接收值。遞歸調(diào)用控制點(diǎn)可以遞歸地應(yīng)用兼容的可恢復(fù)方法,其中所述可恢復(fù)的方法進(jìn)行由該方法使用yield or yield-for_each表達(dá)式所確定的暫停。返回控制點(diǎn)在具有或不具有結(jié)果值的情況下用信號通知可恢復(fù)方法的終止。
提供本發(fā)明內(nèi)容以便以簡化形式介紹將在以下詳細(xì)描述中進(jìn)一步描述的一些概念。本發(fā)明內(nèi)容并不旨在標(biāo)識所要求保護(hù)主題的關(guān)鍵特征或必要特征,也不旨在用于限制所要求保護(hù)主題的范圍。
在附圖中圖I示出了根據(jù)在此公開的主題的各方面的系統(tǒng)100的示例,該系統(tǒng)100提供了處于編程語言外部的用于可恢復(fù)方法的機(jī)制;圖2a — 2d是根據(jù)在此所公開的主題的各方面的驅(qū)動(dòng)程序類的示例;圖2e是根據(jù)在此所公開的主題的各方面的源代碼的示例; 圖2f是根據(jù)在此所公開的主題的各方面的經(jīng)變換代碼的示例;圖2g是根據(jù)本文所公開主題的各方面的經(jīng)改寫方法的示例;圖2h — 2j是根據(jù)在此所公開的主題的各方面的實(shí)現(xiàn)迭代器的可恢復(fù)方法的示例;圖2k是根據(jù)此處所公開的主題的各方面的用于使用外部API來實(shí)現(xiàn)可恢復(fù)方法的方法201的示例的流程圖;圖3是示出了其中可以實(shí)現(xiàn)此處所公開的主題的各方面的計(jì)算環(huán)境的示例的框圖;以及圖4是根據(jù)此處所公開的主題的各方面的集成開發(fā)環(huán)境的示例的框圖。
具體實(shí)施例方式概覽在此公開的主題描述了語言編譯器的特性與插入到編譯器的基于模式的應(yīng)用編程接口(API)插件之間的合約。API插件使該特性適應(yīng)于異步編程、迭代器、對稱協(xié)同例程等等,從而向編譯器提供針對每個(gè)特定類型的可恢復(fù)方法要做些什么的細(xì)節(jié)。該特性重新構(gòu)建輸出代碼(例如中間代碼),從而移除了源代碼與輸出代碼之間的一一對應(yīng)。包括一個(gè)或多個(gè)控制點(diǎn)的源代碼被變換為使得輸出代碼可以在分立的部分中執(zhí)行,每個(gè)部分都在經(jīng)變換的輸出代碼中的控制點(diǎn)處開始和結(jié)束。例如,最終用戶可以編寫傳統(tǒng)的同步代碼,直到他達(dá)到如下的點(diǎn)在該點(diǎn)處,他想要他的代碼能夠暫停以等待某事物而不必停止所有處理。在該點(diǎn)處,最終用戶可以在其代碼中的任何位置、包括在深度嵌套在該語言的控制結(jié)構(gòu)內(nèi)的點(diǎn)處插入控制點(diǎn)。編譯器對控制點(diǎn)的輸入的識別將觸發(fā)對通過源代碼中的控制點(diǎn)表達(dá)的形式(簽名)所標(biāo)識出的API的編譯器變換。被調(diào)用的API確定源代碼中的語言句法的有效性,并且可以在后臺編譯器被使用的情況下展示異步編程特有版本的與編譯器的語言特性的交互。使用外部API來擴(kuò)展編譯器以實(shí)現(xiàn)可恢復(fù)的方法圖I示出了根據(jù)在此公開的主題的各方面的系統(tǒng)100的示例,該系統(tǒng)100提供了處于語言編譯器外部的用于實(shí)現(xiàn)可恢復(fù)方法的機(jī)制。系統(tǒng)100的全部或某些部分可以駐留在諸如下面參考圖3所描述的計(jì)算機(jī)之類的一個(gè)或多個(gè)計(jì)算機(jī)上。系統(tǒng)100的全部或某些部分可以駐留在諸如下面參考圖4所描述的計(jì)算機(jī)之類的一臺或多臺軟件開發(fā)計(jì)算機(jī)(例如,計(jì)算機(jī)102)上。系統(tǒng)100或其一些部分可以包括諸如下面參考圖4所描述的和所示出的那些集成開發(fā)環(huán)境(例如,IDE 104)的一部分。替代地,系統(tǒng)100或其一些部分可以作為獨(dú)立系統(tǒng)或作為插件或附加件來提供。系統(tǒng)100可以包括以下中的一個(gè)或多個(gè)處理器(比如處理器142)、存儲器144、以及提供實(shí)現(xiàn)可恢復(fù)方法的機(jī)制的API或模塊的庫106。也可以包括本領(lǐng)域已知的其他組件,但此處未示出。能夠理解,庫106的一個(gè)或多個(gè)模塊可以被加載到存儲器144中以致使諸如處理器142之類的一個(gè)或多個(gè)處理器執(zhí)行歸因于如下API的動(dòng)作所述API提供了實(shí)現(xiàn)可恢復(fù)方法的機(jī)制,所述機(jī)制處于編程語言之外并且可以插入到語言編譯器中。系統(tǒng)100可以包括下列各項(xiàng)中的一個(gè)或多個(gè)編譯器114,比如后臺編譯器、并行編譯器或增量編譯器;解析器,比如后臺解析器、并行解析器或增量解析器;或者插件、預(yù)處理器、或附件;或者對IDE、解析器、編譯器或預(yù)處理器的擴(kuò)展。在此所述API可被附連到、并入土諸如下列編譯器或與諸如下列編譯器相關(guān)聯(lián) 編譯器,比如后臺編譯器、并行編譯器或增量編譯器;解析器,比如后臺解析器、并行解析器或增量解析器;或者插件、預(yù)處理器、或附件;或者對IDE、解析器、編譯器或預(yù)處理器的擴(kuò)展。編譯器114可以包括與專用API交互的一個(gè)或多個(gè)模塊。在處于語言編譯器外部的庫中提供了特定種類的專用可恢復(fù)方法、比如但不限于異步或迭代器方法。應(yīng)用程序員可以通過如下方式致使這些方法被應(yīng)用于包含傳統(tǒng)編程代碼的方法主體向該傳統(tǒng)代碼添加所述方法本體中的一個(gè)或多個(gè)在句法上可區(qū)分的控制點(diǎn)。包括包含這樣的控制點(diǎn)112的方法108的輸入源代碼可以由編譯器114使用來自庫106的API來變換以生成諸如經(jīng)變換方法110之類的經(jīng)擴(kuò)展方法,其使得經(jīng)變換方法110在被執(zhí)行時(shí)能夠在夾在控制點(diǎn)之間的分立部分中執(zhí)行,這將在下面予以更充分描述??刂泣c(diǎn)是一種如下的點(diǎn)在該點(diǎn)處,方法中的代碼的主體可以要么直接地暫停,要么因?yàn)樵摲椒ㄊ菚和5倪f歸方法調(diào)用的一部分而暫停。不同種類的可恢復(fù)方法的區(qū)別在于該方法在暫停后如何以及何時(shí)恢復(fù),以及在暫停、返回和終止以后哪些變元和返回值來回流動(dòng)。Yield表達(dá)式可以任選地向調(diào)用者返回值,并且從恢復(fù)器或恢復(fù)模塊接收用于暫??刂泣c(diǎn)的值。yield或yieldforeach表達(dá)式可以遞歸地應(yīng)用兼容的可恢復(fù)方法,其中所述可恢復(fù)方法正如該方法所確定的針對遞歸控制點(diǎn)而暫停。返回語句在具有或不具有返回控制點(diǎn)的最終結(jié)果值的情況下用信號通知可恢復(fù)方法的終止。不同種類的可恢復(fù)方法的區(qū)別在于該方法在暫停后如何以及何時(shí)恢復(fù),以及在暫停、返回和終止以后哪些變元和返回值來回流動(dòng)。Yield返回表達(dá)式可以任選地向調(diào)用者返回值,并且從恢復(fù)器或恢復(fù)模塊接收用于暫??刂泣c(diǎn)的值。yield或yieldforeach表達(dá)式可以遞歸地應(yīng)用兼容的可恢復(fù)方法,其中所述可恢復(fù)方法正如該方法所確定的針對遞歸控制點(diǎn)而暫停。返回語句在具有或不具有返回控制點(diǎn)的最終結(jié)果值的情況下用信號通知可恢復(fù)方法的終止?;顒?dòng)的可恢復(fù)方法可以由從諸如可恢復(fù)(Resumable)類之類的可恢復(fù)方法類中派生(derive)的某種類型的巾貞(frame)對象來表示。該對象在方法被掛起時(shí)表示該方法的棧幀。當(dāng)方法被掛起時(shí),表示所掛起方法的棧幀可以被復(fù)制到另一數(shù)據(jù)結(jié)構(gòu)并且可以從機(jī)器棧中移除。因此,所掛起的方法可以在物理上不駐留在棧上。可替代地,棧的整個(gè)狀態(tài)可以被保存,從而無論該方法是活動(dòng)還是掛起都將其維持在堆上。在傳統(tǒng)的不可恢復(fù)的控制流中,機(jī)器使用單個(gè)執(zhí)行線程來執(zhí)行當(dāng)前正等待執(zhí)行的方法的連續(xù)棧。棧上的每個(gè)方法都等待另一方法返回到該方法。棧通常不能直接被編譯器訪問。在實(shí)現(xiàn)可恢復(fù)方法的一些環(huán)境中,可恢復(fù)方法在遇到特定語句時(shí)暫停。此時(shí),根據(jù)在此所公開的主體的各方面,所暫停方法的棧的幀可以被保存并且在該方法恢復(fù)時(shí)被放回到該棧上。關(guān)于什么可恢復(fù)方法調(diào)用了何種可恢復(fù)方法的信息被存儲在單獨(dú)的數(shù)據(jù)結(jié)構(gòu)中,使得當(dāng)方法返回時(shí),該返回可以定向到由負(fù)責(zé)的驅(qū)動(dòng)程序類指定的正確接收者。也就是說,驅(qū)動(dòng)程序類的每個(gè)實(shí)例(即每個(gè)專用對象)都表示機(jī)器棧的所保存的表示中的方法調(diào)用。從特定驅(qū)動(dòng)程序類中實(shí)例化的對象表示執(zhí)行中的特定可恢復(fù)方法調(diào)用。專用對象的集合表示以前由該棧維護(hù)的控制鏈。執(zhí)行中的方法調(diào)用是當(dāng)前正在運(yùn)行或已經(jīng)暫停并還未結(jié)束的任何方法調(diào)用。當(dāng)可恢復(fù)方法返回結(jié)構(gòu)時(shí),其將該結(jié)果提供給調(diào)用該方法的方法并且主調(diào)方法恢復(fù)。根據(jù)在此所公開的主體的一些方面,編譯器生成致使控制轉(zhuǎn)移到所恢復(fù)方法的代碼,從而變換輸入源代碼。當(dāng)可恢復(fù)方法恢復(fù)時(shí),可以調(diào)用Invoke方法或幀對象上的其他調(diào)用方法,所述調(diào)用方法將針對所恢復(fù)方法的真實(shí)激活記錄放回到機(jī)器棧上。如果所暫停方法(第一可恢復(fù)方法)正遞歸地等待另一所掛起的可恢復(fù)方法(第二可恢復(fù)方法),則第二 方法的幀對象可以類似地恢復(fù),使得機(jī)器棧表示可恢復(fù)方法的實(shí)際調(diào)用順序。因此,異常傳播、調(diào)試等等自然可以構(gòu)建在相應(yīng)的內(nèi)建機(jī)制上,比如、但不限于用于異常傳播和調(diào)試的CLR機(jī)制。其他用于棧處理的機(jī)制也是可能的。不同種類的可恢復(fù)方法可以由從抽象可恢復(fù)基類中派生的驅(qū)動(dòng)程序類來定義。圖2a示出了這樣的抽象基類Resumable (可恢復(fù))200的實(shí)例。特定的可恢復(fù)方法可以由作為派生的類編譯器從這些驅(qū)動(dòng)程序類中生成,從而將暫停邏輯實(shí)現(xiàn)為狀態(tài)機(jī)??苫謴?fù)方法的狀態(tài)機(jī)改寫可以被認(rèn)為是發(fā)生在兩個(gè)階段中。第一階段可以將方法主體放置到從驅(qū)動(dòng)程序派生的由編譯器生成的類中的調(diào)用方法的覆蓋(override)中,其中控制點(diǎn)的任何出現(xiàn)都被改寫成下列各項(xiàng)之一a)對驅(qū)動(dòng)程序類中的“之前(before)”方法的調(diào)用,其中任何變元都被傳遞給控制點(diǎn);b)對特定的專用命令的調(diào)用以用于進(jìn)一步改寫;c)對驅(qū)動(dòng)程序類中的“之后(after)”方法的調(diào)用,其中該方法將任何所得到的值傳遞給出現(xiàn)控制點(diǎn)的上下文。在第二階段中,編譯器生成的類和Invoke方法可以用狀態(tài)機(jī)邏輯來擴(kuò)充,并且所述專用命令可以被改寫成用于狀態(tài)變換和掛起的代碼。下面描述語言特性和庫API可以如何使用驅(qū)動(dòng)程序類來交互的實(shí)例。根據(jù)在此所述公開的主體的一些方面,驅(qū)動(dòng)程序類實(shí)現(xiàn)了處于編程語言外部的專用部分。可以使用暫??刂泣c(diǎn)來暫停方法的執(zhí)行。假定特定的方法表達(dá)式了要隨時(shí)間漸進(jìn)地執(zhí)行的工作的主體。為了使方法可返回,可以在方法本體中插入暫??刂泣c(diǎn)。例如如果集合的元素正在被生成,則可以將暫??刂泣c(diǎn)插入在生成下一元素的計(jì)算已經(jīng)被執(zhí)行的點(diǎn)處。在該點(diǎn)處,元素可以被yield返回。當(dāng)集合的下一元素被請求時(shí),該方法可以恢復(fù)并且可以在從中作出yield返回的點(diǎn)處返回。遞歸控制點(diǎn)每當(dāng)被調(diào)方法暫停時(shí)都暫停作出遞歸調(diào)用的方法。例如,假定第一迭代器可以yield3個(gè)元素(一次一個(gè)),并且第二迭代器可以yield 2個(gè)元素(一次一個(gè)),這兩個(gè)迭代器可以通過創(chuàng)建可調(diào)用其他可恢復(fù)方法的可恢復(fù)方法被組裝成能夠順序地yield全部5個(gè)元素的迭代器。所組裝的迭代器方法可以首先調(diào)用第一迭代器并且使其一次一個(gè)地yield它的三個(gè)元素。當(dāng)?shù)谝坏饕呀?jīng)yield出了所有三個(gè)元素時(shí),所組裝的方法可以調(diào)用第二迭代器,所述第二迭代器yield出其他兩個(gè)元素。當(dāng)?shù)谝坏鲿和r(shí),所組裝的迭代器方法被暫停。類似地,當(dāng)?shù)诙鲿和r(shí),所組裝的迭代器方法被暫停。返回控制點(diǎn)用信號通知可恢復(fù)方法的終止,并且被用于定義在工作完成時(shí)要做些什么。盡管可能在一路上發(fā)生了若干暫停和若干恢復(fù),但是該工作最終完成。返回可以僅僅指示該工作完成,或者也可以包括已完成的工作的結(jié)果。異步方法可以每當(dāng)?shù)却龝r(shí)間周期長時(shí)使用,例如在輸入輸出操作期間或者針對通過網(wǎng)絡(luò)的通信來使用。例如假定用戶想要從網(wǎng)頁下載某些信息,對所下載的信息執(zhí)行某種計(jì)算,并且將計(jì)算結(jié)果發(fā)送給另一網(wǎng)頁。當(dāng)所述操作完成時(shí),將返回指示成功或失敗的布爾結(jié)果。為了同步地執(zhí)行這些操作,通常使用調(diào)用兩個(gè)助手方法的方法。所述助手方法之一通常導(dǎo)航到該網(wǎng)頁并且提取所期望的內(nèi)容。在內(nèi)容被接收以后,執(zhí)行該計(jì)算。第二助手方法通常被調(diào)用以將計(jì)算結(jié)果發(fā)送給另一網(wǎng)頁。當(dāng)完成時(shí),該方法返回布爾結(jié)果。該情況中的同步處理尤其是在進(jìn)行到該網(wǎng)頁的連接并且所下載的內(nèi)容被檢索時(shí)以及還有在計(jì)算結(jié)果被發(fā)送給第二網(wǎng)頁時(shí)導(dǎo)致等待時(shí)間段。根據(jù)連接速率、網(wǎng)絡(luò)通信量以及所下載信息的大 小,等待時(shí)間可以是顯著的。使用異步方法執(zhí)行該系列動(dòng)作將釋放操作系統(tǒng)線程資源,這可以導(dǎo)致更好的用戶體驗(yàn)。例如,在任何基于GUI的應(yīng)用中,僅僅單個(gè)線程服務(wù)于用戶輸入事件,使得釋放線程失敗可能導(dǎo)致非常差的用戶體驗(yàn)。然而,在沒有語言支持的情況下實(shí)現(xiàn)異步方法是困難的,因?yàn)椴荒苁褂谜5目刂平Y(jié)構(gòu)。因此,程序員必須人工地編寫和調(diào)試嵌套回調(diào)、一種困難和易錯(cuò)的任務(wù),從而導(dǎo)致代碼也難以閱讀和維護(hù)。此外,代碼的復(fù)雜度隨著方法內(nèi)的經(jīng)“人工”(非程序性地)變換的控制點(diǎn)的數(shù)目增長而迅速增加。根據(jù)在此公開的主體的各方面,控制點(diǎn)可以以任意嵌套深度被放置在正常的控制結(jié)構(gòu)內(nèi)。可以在異步驅(qū)動(dòng)程序類所支持的異步方法內(nèi)進(jìn)行遞歸調(diào)用。回調(diào)由編譯器生成,其中回調(diào)該方法但是是對開發(fā)者透明的。在從網(wǎng)頁下載的示例中,異步方法首先yield到從web讀取的方法,計(jì)算被執(zhí)行,然后對方法進(jìn)行遞歸yield,該方法將計(jì)算結(jié)果發(fā)送給第二網(wǎng)頁,并且最終布爾結(jié)果被返回。因此,控制流與在同步方法的情況下一樣,但是處理器從不空閑。迭代器類似地工作,只是客戶端觸發(fā)集合的下一元素的生成、而不是來自網(wǎng)頁的回調(diào)觸發(fā)下一步驟。不同的環(huán)境組驅(qū)動(dòng)由驅(qū)動(dòng)類的特性描述的不同過程。因此,上述不同類型的控制點(diǎn)實(shí)現(xiàn)了向傳統(tǒng)方法那樣的對可恢復(fù)方法的組裝,而無須開發(fā)者應(yīng)付可恢復(fù)方法的復(fù)雜度??苫謴?fù)的方法可以通過調(diào)用其他異步或可恢復(fù)方法或者通過該方法遞歸地調(diào)用其自身來組裝。盡管一般而言,迭代器可以調(diào)用其他迭代器并且異步方法可以調(diào)用其他異步方法,但是根據(jù)在此所述的主體的各方面,驅(qū)動(dòng)程序類規(guī)定何種可恢復(fù)方法可以從特定的可恢復(fù)方法中調(diào)用,使得可恢復(fù)方法不限于調(diào)用相同類型的另一可恢復(fù)方法。如上所述,表示執(zhí)行控制鏈(例如棧)的專用對象可以由編譯器從專用抽象基類中生成。專用抽象基類包括特定行為和方法。例如,抽象類AsynchCD (圖2d中示出)可以被編譯器用于作出包括Asynch〈T>類的特定方法主體的所派生的類。所派生的Asynch〈T>類被實(shí)例化成幀對象。該幀對象中的代碼的一部分可以由來自庫的專用基類來貢獻(xiàn),并且其一部分可以由可放入該方法特有的邏輯中的編譯器來貢獻(xiàn)。在經(jīng)變換或擴(kuò)充版本的方法中,將存在對從基類庫中繼承的專用方法的調(diào)用,上述方案的替代方案包括創(chuàng)建兩個(gè)對象,ー個(gè)對象通過包含核幀對象的編譯器來創(chuàng)建,一個(gè)對象由庫來提供,其中所述對象通過它們的方法彼此通信。根據(jù)在此所述的主體的各方面,在每個(gè)控制點(diǎn)處,編譯器生成代碼可以在驅(qū)動(dòng)程序類上的方法暫停以前調(diào)用該方法,并且可以在驅(qū)動(dòng)程序類上的方法恢復(fù)以后調(diào)用該方法,以向該方法提供執(zhí)行其專用行為的機(jī)會。例如,對于yield控制點(diǎn)而言,存在編譯器生成的代碼將在基類上調(diào)用的之前yield方法和之后yield方法。對于返回的遞歸調(diào)用而言,存在之前yield返回方法和之后yield返回方法,并且對于返回而言,存在之前返回方法而不存在之后返回方法,因?yàn)榉椒ㄔ谄渫瓿蓵r(shí)返回。之前和之后方法調(diào)用使得驅(qū)動(dòng)程序類能夠指定要執(zhí)行的方法。如果驅(qū)動(dòng)程序類未指定之前yield或之后yield方法,則編譯器不能生成對它們的方法調(diào)用,使得使用這種控制點(diǎn)將在由該驅(qū)動(dòng)程序類管理的可恢復(fù)方法中為非法的。因此,驅(qū)動(dòng)程序類可以通過指定之前和之后方法或者通過未能指定之前和之后方法來指定這些控制點(diǎn)中的哪些是可用的。附加于確定特定控制點(diǎn)是否為可用的,驅(qū)動(dòng)程序類可以確定控制點(diǎn)對哪些情形可用。由于該交互是基于模式的并且該模式確定編譯器生成的代碼調(diào)用哪個(gè)方法,因此通過指定該方法采取哪些變元,驅(qū)動(dòng)程序類可以指定哪些方法可以被遞歸地調(diào)用。可以存在方法的多個(gè)過載(overload),使得例如異步方法可以被允許調(diào)用多種類型的異步方法,這可以實(shí)現(xiàn)不同模型之間的互操作。類似地,變元類型化的指定可以用于調(diào)用由當(dāng)前處于庫中的任務(wù)類表示的方法。
最后,驅(qū)動(dòng)程序類可以確定該方法的本體中有些什么,也就是說,驅(qū)動(dòng)程序特有的行為在yield以前是什么樣的。例如,ー些數(shù)據(jù)可以在幀類之間轉(zhuǎn)移,或者處理可以被執(zhí)行以使數(shù)據(jù)表示為恢復(fù)做好準(zhǔn)備。關(guān)于迭代器,之前yield返回方法調(diào)用可以指定集合的下一元素值如何被yield,并且如何將該值傳輸給客戶端。之前和之后方法是開放式的,并且可以用于實(shí)現(xiàn)迭代器、異步方法及其變型。例如,各個(gè)異步方法可以由參數(shù)化的驅(qū)動(dòng)程序類來表示,所述驅(qū)動(dòng)程序類可以由最終用戶創(chuàng)建以用于任何命令性的編程語言。圖2a — 2d示出了實(shí)現(xiàn)上述方面的驅(qū)動(dòng)程序類的非限制性示例。能夠理解,盡管所提供的示例使用按照名稱標(biāo)識出方法的特定句法形式,但是可以使用不限于命名方法的其他句法形式。圖2a示出了可從中派生服務(wù)特有的驅(qū)動(dòng)程序類的可恢復(fù)方法(類Resumable 200)的系統(tǒng)范圍的基類的示例。圖2b示出了抽象類AsyncResumable 210的示例,所述抽象類從類Resumable 200中派生并且是異步特有的。圖2c和2d中示出了抽象類 AsyncResumable 210 的兩個(gè)變型。從抽象類 AsyncResumable 210 派生的類 Async 220、以及也是從抽象類AsyncResumable 210派生的類Async〈T>230。類Async 220被用于創(chuàng)建表示不具有結(jié)果的異步操作的對象。類Async〈T>230是通用類,其用于創(chuàng)建表示具有類型T的結(jié)果的異步操作的對象。AsyncResumable 210 的主體包括 BeforeYield (之前 Yield)方法 212 和AfterYield (之后Yield)方法214。之前方法(例如BeforeYield方法212)和之后方法(例如AfterYield方法214)的簽名描述了可以遞歸地調(diào)用的方法的類型,并且保證返回值被正確地生成和消費(fèi)。當(dāng)在類定義中缺少之前返回方法的類型時(shí),調(diào)用那種返回是非法的(例如在類Async 220的定義和類Async〈T>的定義中缺少BeforeYieldReturn方法意味著在這些異步方法中調(diào)用YieldReturn是非法的)。BeforeYield和AfterYield方法在AsyncResumable 210的類定義中的存在指不從AsyncResumable方法中,yield是可能的。由于缺少BeforeYieldReturn方法和AfterYieldReturn,因此yield返回控制點(diǎn)不能用在AsyncResumable方法中??梢詙ield其他異步方法,除了異步方法以外的方法不能被yield。類Async 220和Async〈T>230的定義包括其他返回方法。類Asynch 220的BeforeReturn方法222指示在沒有結(jié)果值的情況下僅能進(jìn)行返回,因此其不采取變元。類Asynch<T>230的BeforeReturn方法232指不該方法返回類型T的值,因此BeforeReturn方法232采取類型T的變元。因此,如果“返回7”被包括在返回Async〈int>的可恢復(fù)方法的主體中,則編譯器生成的利用變元7對BeforeReturn的調(diào)用將無問題地解析到BeforeReturn方法232。然而,如果方法嘗試向Async〈int>方法返回 字符串,貝U編譯器將發(fā)現(xiàn)簽名不匹配并且將返回編譯時(shí)錯(cuò)誤。圖2e示出了最終用戶可以編寫的包括異步可恢復(fù)方法240的代碼的代碼段的示例。該方法可以通過返回Async〈int> (上述驅(qū)動(dòng)程序類之一)的語句staticAsync〈int>M() 242而被確定為異步的。處于可恢復(fù)方法240內(nèi)的是正??刂屏鞔a,該代碼將“之前(before)”寫入控制臺(console),并且然后yieldx (int x=yieldWait (10);語句244)。該行代碼的控制點(diǎn)是“yield”表達(dá)式,其觸發(fā)方法240到圖2f中所示方法250的轉(zhuǎn)換。方法250被改寫以生成如圖2g方法260中所示的MFrame類的實(shí)例。編譯器生成稱為MFrame的從Async〈int>中派生的類,并且如圖2f所示擴(kuò)充yield和返回的出現(xiàn)。能夠理解,經(jīng)擴(kuò)充的方法250覆蓋所調(diào)用方法(public override void Invoke () {)(語句251)并且現(xiàn)在具有用戶編寫的代碼以及通過其中的編譯器生成的附加代碼。Console.WriteLine (“之前”)和Console. WriteLine (“之后”)語句仍然在那里,但是在這兩個(gè)語句之間,方法240的語句int x=yield Wait (10)語句244已經(jīng)被擴(kuò)充到調(diào)用Wait (10)語句252并且然后調(diào)用BeforeYield語句253的代碼中。調(diào)用BeforeYield的結(jié)果是,該方法的執(zhí)行暫停,這由行CALL(tmp2);語句254中的“CALL”來指示?!癈ALL”和“返回”在調(diào)用方法的主體中的出現(xiàn)用信號向編譯器通知狀態(tài)機(jī)控制代碼必須被插入在這些點(diǎn)處。對Before (之前)和After (之后)方法的調(diào)用是從原始源代碼的句法中生成的。編譯器可以對照AsyncCD中提供的方法使用方法綁定規(guī)則和技術(shù)來檢查調(diào)用,并且在方法未被正確使用時(shí)提出錯(cuò)誤。因此,遞歸調(diào)用被充分強(qiáng)地類型化。當(dāng)方法恢復(fù)時(shí),方法AfterYield被調(diào)用(在行var tmp3=AfterYield (tmp2);語句255中)。調(diào)用AfterYield的結(jié)果可以被放入變量tmp3中。tmp3變量的內(nèi)容通過下列用戶編寫代碼被分配給變量X x=tmp3; statement 256,“之后”被寫入到控制臺中(語句259), x通過調(diào)用BeforeReturn(X)被返回(語句258),并且返回行語句259被執(zhí)行。圖2h — j示出了實(shí)現(xiàn)迭代器的可恢復(fù)方法的示例。圖2h中所示的驅(qū)動(dòng)程序類270聲明了稱為Iterator (迭代器)的抽象類,該抽象類是從抽象類Resumable派生的并且實(shí)現(xiàn) IEnumerator 接 ロ(abstract class Iterator; Resumable, IEnumeratorX IEnumerator接ロ具有稱為MoveNext的方法,該方法移動(dòng)到集合中的下一元素。IEnumerator接ロ還具有Current (當(dāng)前)屬性,其中存儲了集合中的當(dāng)前元素(MoveNext所移動(dòng)到的元素)的值。姆當(dāng)MoveNext方法在Iterator上被調(diào)用時(shí),該方法的具有其中的控制點(diǎn)的下一部分可以被執(zhí)行。驅(qū)動(dòng)程序類 270 為 YieIdReturruYieldForeach、YieldBreak(return)提供與針對Async類的類似方法不同的“Before”和“After”方法。該示例中的YieldForeach的過載的數(shù)目展示了該方法的強(qiáng)大。例如,一個(gè)過載的YieldForeach從可枚舉(enumerable)獲得枚舉器并且將其變換成迭代器并且遞歸地調(diào)用該迭代器?!癙AUSE (暫停)”命令可以用于改寫YieldReturn控制點(diǎn)。圖2i示出了簡單的迭代器、即靜態(tài)迭代器F 280。迭代器F 280包括控制點(diǎn)、SPyield返回語句(“yield return I; ”語句282),其直接生成集合的元素并且然后暫停。迭代器F 280還包括控制點(diǎn)“yield foreachF O ; ”語句284,其遞歸地調(diào)用迭代器F直到F用完了集合中的元素。因此,多個(gè)值可以利用yield之間的暫停來yield。語句“yield return2; ”語句286返回其他值?!皔ield break;”125085 IPffCN
語句288在集合的所有元素都已經(jīng)被yield時(shí)執(zhí)行。迭代器F 280可以由編譯器來翻譯,這如圖2j中所示。從圖2j中可以得知,Iterator F O中的每個(gè)控制點(diǎn)都可以被轉(zhuǎn)換成對“之前”和“之后”方法的調(diào)用(例如圖2j中所示語句“yield return I”語句282被變換成如圖2j中所示的對BeforeYieldReturn(I)的調(diào)用語句292、如語句294中所示對PAUSE的調(diào)用、以及如語句296中所不對AfterYieldReturn的調(diào)用)。類似地,YieldForeachF O ;語句284被翻譯成圖2j中的單個(gè)語句298中所不的BeforeYieldForeach語句、CALL語句和AfterYieldForeach語句。當(dāng)?shù)鱂 280被執(zhí)行時(shí),具有值的yield返回被返回(語句292),PAUSE語句294致使方法掛起執(zhí)行,并且當(dāng)該方法恢復(fù)吋,該方法將如語句296中所示調(diào)用AfterYieldReturn 方法。如圖 2h 語句 272 中所不,BeforeYieldReturn 從 Iterator 類繼承,從而將當(dāng)前值設(shè)置為對象O,使得當(dāng)對MoveNext的調(diào)用完成吋,當(dāng)前值將被返回。三個(gè)語句298中所示的語句對語句284的YieldForeach控制點(diǎn)類似地操作以用于遞歸調(diào)用,并且達(dá)到三個(gè)過載、即過載274、過載276和過載278。這三個(gè)不同的過載允許不同的YieldForeach方法采取不同的變元并且通過集合的不同表示來實(shí)現(xiàn)yield。第一過載、即過載274遞歸地調(diào)用另ー迭代器。針對第二過載、即過載276, Enumerable (可枚舉)表示對象的集合并且具有稱為Get Enumerator的方法。當(dāng)Get Enumerator被調(diào)用時(shí),該集合的新元素被獲得。當(dāng)?shù)竭_(dá)該集合的結(jié)尾時(shí),不再能獲得元素。最后ー個(gè)過載、即過載278使得能夠獲得該集合的新實(shí)例。將調(diào)用方法最終變換成狀態(tài)機(jī)類似于在此所述的迭代器和異步方法的變換。每個(gè)PAUSE和CALL都被分配狀態(tài)。在方法的開始處和每個(gè)嘗試塊的開始處添加邏輯以分叉到該代碼中與當(dāng)前狀態(tài)相關(guān)聯(lián)的點(diǎn)。PAUSE點(diǎn)暫停或掛起方法的執(zhí)行并且將狀態(tài)推進(jìn)到緊接在PAUSE以后并且返回。后面的恢復(fù)將重新調(diào)用該調(diào)用方法,從而分叉到緊接在PAUSE命令之后的點(diǎn)。CALL點(diǎn)不掛起執(zhí)行。相反,其開始對被調(diào)用的可恢復(fù)方法的執(zhí)行。被調(diào)用的可恢復(fù)方法可以包括諸如PAUSE之類的控制點(diǎn),使得被調(diào)用的可恢復(fù)方法本身可以暫停或掛起,從而致使整個(gè)棧被暫停(包括主調(diào)方法)。通過組合迭代器和異步方法,可以創(chuàng)建諸如IAsyncEnumerator之類的用戶定義的驅(qū)動(dòng)程序類,其中IEnumerator MoveNext方法是異步的。這樣的組合方法可以遞歸地調(diào)用異步方法和同步迭代器二者,從而實(shí)現(xiàn)各種附加的控制點(diǎn)。對稱協(xié)同例程可以通過創(chuàng)建協(xié)作方法實(shí)現(xiàn),其中所述協(xié)作方法彼此傳遞控制(而不是返回到彼此),同時(shí)保留毎次恢復(fù)之間的執(zhí)行狀態(tài)。與異步方法的某些實(shí)施方式不同,協(xié)作方法可以不增加調(diào)用棧的深度。相反,調(diào)用棧的葉幀可以被換出。圖2k是用于使用外部API來擴(kuò)展編譯器以實(shí)現(xiàn)可恢復(fù)方法的方法201的示例。在203,可以由編譯器接收源代碼。該編譯器可以是諸如參照圖I所述的編譯器之類的編譯器。響應(yīng)于識別在句法上可區(qū)分的控制點(diǎn)(比如上述暫停、遞歸調(diào)用和返回控制點(diǎn)),在205,編譯器可以調(diào)用由控制點(diǎn)表達(dá)式的簽名確定的外部API。如上所述,被調(diào)用的API可以是專用方法并且可以駐留在編譯器外部的庫中。如上所述,表示控制鏈(例如棧)的專用對象可以由編譯器從庫中的專用抽象基類中生成??商娲兀娲谡{(diào)用抽象基類,可以調(diào)用符合控制點(diǎn)表達(dá)式的簽名的任何代碼,包括但不限于非抽象基類、接ロ、具有擴(kuò)展方法的靜態(tài)類等等。專用抽象基類或其他代碼可以包括專用行為以及諸如異步和迭代器方法之類的方法。例如,抽象類Asynch〈T> (圖2b中示出)可以被編譯器用于作出包括Asynch〈T>類的特定方法主體的派生的類。 派生的可恢復(fù)類可以被實(shí)例化成諸如例如幀對象之類的對象。該對象中的代碼的一部分可以由來自庫的專用基類來貢獻(xiàn)。該對象中的代碼的一部分可以由編譯器來貢獻(xiàn),其中該編譯器放入該方法特有的邏輯。在209,所接收的源代碼可以被變換成經(jīng)擴(kuò)充的代碼,使得在所接收的源代碼中的每個(gè)控制點(diǎn)處,編譯器生成代碼可以在驅(qū)動(dòng)程序類上的方法暫停以前調(diào)用該方法,并且可以在驅(qū)動(dòng)程序類上的方法恢復(fù)以后調(diào)用該方法,以向該方法提供執(zhí)行其專用行為的機(jī)會。例如,編譯器生成的代碼可以調(diào)用基類上的之前yield方法和之后yield方法。針對返回的遞歸調(diào)用,編譯器生成的代碼可以調(diào)用之前yield返回方法和之后yield返回方法。類似地,對于返回,編譯器生成的代碼可以調(diào)用之前返回方法、但不是之后返回方法,因?yàn)榉椒ㄔ谄渫瓿蓵r(shí)返回。之前和之后方法調(diào)用使得驅(qū)動(dòng)程序類能夠指定要執(zhí)行的方法、以及由此哪些種類的控制點(diǎn)在特定可恢復(fù)方法中是合法的、以及控制點(diǎn)對哪些情形可用。由于該交互是基于模式的并且該模式確定編譯器生成的代碼調(diào)用哪個(gè)方法,因此通過指定該方法采取哪些變元,驅(qū)動(dòng)程序類可以指定哪些方法可以被遞歸地調(diào)用??梢源嬖诜椒ǖ亩鄠€(gè)過載,使得例如異步方法可以被允許調(diào)用多種類型的異步方法,這可以實(shí)現(xiàn)不同模型之間的互操作。驅(qū)動(dòng)程序類可以確定與對象相關(guān)聯(lián)的特定行為。在211,可以創(chuàng)建可執(zhí)行代碼。合適的計(jì)算環(huán)境的示例為了提供有關(guān)本文所公開的主題的各個(gè)方面的上下文,圖3以及以下討論g在提供其中可以實(shí)現(xiàn)各實(shí)施例的合適的計(jì)算環(huán)境510的簡要概括描述。盡管本文所公開的主題是在諸如程序模塊等由一個(gè)或多個(gè)計(jì)算機(jī)或其它計(jì)算設(shè)備執(zhí)行的計(jì)算機(jī)可執(zhí)行指令的通用上下文中描述的,但本領(lǐng)域技術(shù)人員將認(rèn)識到,本文所公開的主題的各部分還能夠結(jié)合其它程序模塊和/或硬件和軟件的組合來實(shí)現(xiàn)。通常,程序模塊包括執(zhí)行特定任務(wù)或?qū)崿F(xiàn)特定數(shù)據(jù)類型的例程、程序、對象、物理人為產(chǎn)物、數(shù)據(jù)結(jié)構(gòu)等。通常,程序模塊的功能可在各個(gè)實(shí)施例中按需進(jìn)行組合或分布。計(jì)算環(huán)境510只是合適的操作環(huán)境的ー個(gè)示例,并且不旨在對此處所公開的主題的使用范圍或功能提出任何限制。
參照圖3,描述了計(jì)算機(jī)512形式的用于線性棧上高效恢復(fù)協(xié)同例程的計(jì)算設(shè)備。計(jì)算機(jī)512可包括處理單元514、系統(tǒng)存儲器516和系統(tǒng)總線518。處理單元514可以是各種可用處理器中的任何ー種。也可以使用雙微處理器及其他多處理器體系結(jié)構(gòu)作為處理單元514。系統(tǒng)存儲器516可包括易失性存儲器520和非易失性存儲器522。非易失性存儲器522可包括只讀存儲器(ROM)、可編程ROM (PROM)、電可編程ROM (EPROM)或閃存。易失性存儲器520可包括可充當(dāng)外高速緩沖存儲器的隨機(jī)存取存儲器(RAM)。系統(tǒng)總線518將包括系統(tǒng)存儲器516的系統(tǒng)物理人為產(chǎn)物耦合到處理單元514。系統(tǒng)總線518可以是幾種類型的總線結(jié)構(gòu)中的任何ー種,包括存儲器總線、存儲控制器、外圍總線、外總線或局部總線,并且可以使用各種可用總線體系結(jié)構(gòu)中的任ー種。計(jì)算機(jī)512通常包括各種計(jì)算機(jī)可讀介質(zhì),諸如易失性和非易失性介質(zhì)、可移動(dòng)和不可移動(dòng)介質(zhì)。計(jì)算機(jī)存儲介質(zhì)可以通過用于存儲諸如計(jì)算機(jī)可讀指令、數(shù)據(jù)結(jié)構(gòu)、程序模塊或其它數(shù)據(jù)等信息的任何方法或技術(shù)來實(shí)現(xiàn)。計(jì)算機(jī)存儲介質(zhì)包括但不限干,RAM、R0M、EEPR0M、閃存或其它存儲器技術(shù)、⑶ROM、數(shù)字多功能盤(DVD)或其它光盤存儲、磁盒、磁 帶、磁盤存儲或其它磁存儲設(shè)備、或可以用來儲存所期望的信息并可由計(jì)算機(jī)512訪問的任何其他瞬態(tài)或非瞬態(tài)介質(zhì)。將理解,圖3描述了可充當(dāng)用戶與計(jì)算機(jī)資源之間的媒介的軟件。該軟件可以包括可存儲在盤存儲524上的操作系統(tǒng)528,該操作系統(tǒng)可控制并分配計(jì)算機(jī)系統(tǒng)512的資源。盤存儲524可以是通過諸如接ロ 526的不可移動(dòng)存儲器接ロ連接到系統(tǒng)總線518的硬盤驅(qū)動(dòng)器。系統(tǒng)應(yīng)用程序530利用由操作系統(tǒng)528通過存儲在系統(tǒng)存儲器516或者存儲在盤存儲524上的程序模塊532和程序數(shù)據(jù)534對資源的管理??梢岳斫?,計(jì)算機(jī)可用各種操作系統(tǒng)或操作系統(tǒng)的組合來實(shí)現(xiàn)。用戶可通過輸入設(shè)備536向計(jì)算機(jī)512輸入命令或信息。輸入設(shè)備536包括但不限于定點(diǎn)設(shè)備,諸如鼠標(biāo)、跟蹤球、指示筆、觸摸墊、鍵盤、話筒等。這些及其他輸入設(shè)備通過系統(tǒng)總線518經(jīng)由接ロ端ロ 538連接到處理單元514。接ロ端ロ 538可表示串行端ロ、并行端ロ、通用串行總線(USB)等。輸出設(shè)備540可與輸入設(shè)備使用相同類型的端ロ。提供輸出適配器542以舉例說明存在像監(jiān)視器、揚(yáng)聲器、以及打印機(jī)的需要特定適配器的ー些輸出設(shè)備540。輸出適配器542包括但不限于,在輸出設(shè)備540和系統(tǒng)總線518之間提供連接的視頻卡和聲卡。其他設(shè)備和/或系統(tǒng)和/或設(shè)備,諸如遠(yuǎn)程計(jì)算機(jī)544,可提供輸入和輸出兩種能力。計(jì)算機(jī)512可以使用到諸如遠(yuǎn)程計(jì)算機(jī)544之類的ー個(gè)或多個(gè)遠(yuǎn)程計(jì)算機(jī)的邏輯連接來在聯(lián)網(wǎng)環(huán)境中操作。遠(yuǎn)程計(jì)算機(jī)544可以是個(gè)人計(jì)算機(jī)、服務(wù)器、路由器、網(wǎng)絡(luò)PC、對等設(shè)備或其它常見的網(wǎng)絡(luò)節(jié)點(diǎn),并且通常包括許多或所有以上相對于計(jì)算機(jī)512所描述的元件,盡管在圖4中僅示出了存儲器存儲設(shè)備546。遠(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是指用來將網(wǎng)絡(luò)接ロ 548連接到總線518的硬件/軟件。連接550可以在計(jì)算機(jī)512內(nèi)或外并且包括諸如調(diào)制解調(diào)器(電話、電纜、DSL和無線)和ISDN適配器、以太網(wǎng)卡等內(nèi)和外技木。可以理解,所示網(wǎng)絡(luò)連接僅是示例,并且可以使用在計(jì)算機(jī)之間建立通信鏈路的其它手段。本領(lǐng)域的普通技術(shù)人員可以理解,計(jì)算機(jī)512或其它客戶機(jī)設(shè)備可作為計(jì)算機(jī)網(wǎng)絡(luò)的一部分來部署。在這一點(diǎn)上,本文所公開的主題涉及具有任意數(shù)量的存儲器或存儲單元以及在任意數(shù)量的存儲單元或卷上發(fā)生的任意數(shù)量的應(yīng)用和進(jìn)程的任何計(jì)算機(jī)系統(tǒng)。本文所公開的主題的各方面可應(yīng)用于具有部署在網(wǎng)絡(luò)環(huán)境中的具有遠(yuǎn)程或本地存儲的服務(wù)器計(jì)算機(jī)和客戶計(jì)算機(jī)的環(huán)境。本文所公開的主題的各方面也可應(yīng)用于具有編程語言功能、解釋和執(zhí)行能力的獨(dú)立計(jì)算設(shè)備。圖4示出集成開發(fā)環(huán)境(IDE) 600和通用語言運(yùn)行時(shí)環(huán)境602。IDE 600可允許用戶(例如,開發(fā)者、程序員、設(shè)計(jì)者、編碼者等)在計(jì)算機(jī)系統(tǒng)中設(shè)計(jì)、編碼、編譯、測試、運(yùn)行、編輯、調(diào)試或構(gòu)建程序、程序集、網(wǎng)站、web應(yīng)用和web服務(wù)。軟件程序可包括以ー種或多種源代碼語言(例如,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ī)代碼開發(fā)環(huán)境,或者可提供在虛擬機(jī)上運(yùn)行的托管代碼開發(fā),或者可提供其組合。IDE 600可提供使用.NET框架的托管代碼開發(fā)環(huán)境。可使用語言專用源編譯器620從源代碼組件610和本機(jī)代碼組件611創(chuàng)建中間語言組件650,并且在執(zhí)行應(yīng)用時(shí)使用中間語言編譯器660 (例如,即時(shí)(JIT)編譯器)從中間語 言組件650創(chuàng)建本機(jī)代碼組件611 (例如,機(jī)器可執(zhí)行指令)。S卩,當(dāng)IL應(yīng)用被執(zhí)行時(shí),其在被執(zhí)行的同時(shí)被編譯成適合正在其上執(zhí)行它的平臺的合適機(jī)器語言,藉此使代碼能跨若干平臺便攜。替代地,在其他實(shí)施例中,程序可被編譯成適合其目標(biāo)平臺的本機(jī)代碼機(jī)器語言(未示出)。用戶可根據(jù)已知軟件編程技術(shù)以及與特定源語言相關(guān)聯(lián)的特定邏輯和句法規(guī)則經(jīng)由IDE 600中的用戶接ロ 640和源代碼編輯器651來創(chuàng)建和/或編輯源代碼組件。此后,源代碼組件610可經(jīng)由源編譯器620被編譯,藉此可創(chuàng)建該程序的中間語言表示,諸如匯編630。匯編630可包括中間語言組件650和元數(shù)據(jù)642。應(yīng)用設(shè)計(jì)可以能夠在部署前被驗(yàn)證。本文所述的各種技術(shù)可結(jié)合硬件或軟件,或在適當(dāng)時(shí)以其組合來實(shí)現(xiàn)。由此,本文所公開的方法和裝置或其特定方面或部分可采取包含在諸如軟盤、CD-ROM、硬盤驅(qū)動(dòng)器或任何其它機(jī)器可讀存儲介質(zhì)等有形介質(zhì)中的程序代碼(即,指令)的形式,其中當(dāng)程序代碼被加載到諸如計(jì)算機(jī)等機(jī)器內(nèi)并由其執(zhí)行時(shí),該機(jī)器成為用于實(shí)現(xiàn)本文所公開的主題的各方面的裝置。在程序代碼在可編程計(jì)算機(jī)上執(zhí)行的情況下,計(jì)算設(shè)備通常將包括處理器、該處理器可讀的存儲介質(zhì)(包括易失性和非易失性的存儲器和/或存儲元件)、至少ー個(gè)輸入設(shè)備、以及至少ー個(gè)輸出設(shè)備。可例如通過使用數(shù)據(jù)處理API等來利用域?qū)S镁幊棠P透鞣矫娴膭?chuàng)建和/或?qū)崿F(xiàn)的一個(gè)或多個(gè)程序可用高級過程語言或面向?qū)ο蟮木幊陶Z言來實(shí)現(xiàn)以與計(jì)算機(jī)系統(tǒng)通信。然而,如果需要,該程序可以用匯編語言或機(jī)器語言來實(shí)現(xiàn)。在任何情形中,語言可以是編譯語言或解釋語言,且與硬件實(shí)現(xiàn)相結(jié)合。雖然已結(jié)合附圖描述了本文所公開的主題,但是應(yīng)理解,可作出修改以按不同方式執(zhí)行相同功能。
權(quán)利要求
1.一種系統(tǒng),包括 處理器和存儲器;以及 編譯器,所述編譯器被配置為致使所述處理器 接收包括可恢復(fù)方法的源代碼,所述可恢復(fù)方法包括在句法上可區(qū)分的控制點(diǎn)表達(dá)式,所述控制點(diǎn)表達(dá)式具有簽名,其中所述編譯器調(diào)用多個(gè)程序模塊中的程序模塊,被調(diào)用的程序模塊是由所述控制點(diǎn)表達(dá)的簽名確定的,其中所述編譯器從被調(diào)用的程序模塊中創(chuàng)建至少一個(gè)專用對象;以及 加載處于所述編譯器外部的庫,所述庫包括所述多個(gè)程序模塊。
2.如權(quán)利要求I所述的系統(tǒng),其特征在于,由所述編譯器創(chuàng)建的多個(gè)專用對象表示執(zhí)行控制鏈。
3.如權(quán)利要求I所述的系統(tǒng),其特征在于,被調(diào)用的程序模塊包括專用行為和專用方法,并且其中所述專用方法包括可恢復(fù)方法,所述可恢復(fù)方法包括異步方法或迭代器方法或?qū)ΨQ協(xié)同例程方法。
4.如權(quán)利要求I所述的系統(tǒng),其特征在于,所述編譯器將所接收的源代碼中的控制點(diǎn)表達(dá)式中的控制點(diǎn)改寫成對在所述可恢復(fù)方法暫停之前執(zhí)行的方法的調(diào)用、以及對在所述可恢復(fù)方法恢復(fù)之后執(zhí)行的方法的調(diào)用。
5.如權(quán)利要求4所述的系統(tǒng),其特征在于,用狀態(tài)機(jī)邏輯擴(kuò)充派生的類,并且將專用命令改寫成用于狀態(tài)變換和掛起的派生的類。
6.一種方法,包括 在軟件開發(fā)計(jì)算機(jī)上的編譯器中接收源代碼,所述源代碼包括可恢復(fù)方法,所述可恢復(fù)方法包括在句法上可區(qū)分的控制點(diǎn)表達(dá),其中所述編譯器調(diào)用基于基于模式的交互的代碼,所述代碼處于所述編譯器外部的庫中,所述編譯器從所述代碼中派生專用驅(qū)動(dòng)程序類; 從派生的專用驅(qū)動(dòng)程序類中實(shí)例化對象,所述對象表示包括異步方法或迭代器或?qū)ΨQ協(xié)同例程的可恢復(fù)方法。
7.如權(quán)利要求6所述的方法,其特征在于,所述專用驅(qū)動(dòng)程序類包括專用行為和專用方法。
8.如權(quán)利要求8所述的方法,其特征在于,還包括 將所接收的源代碼變換成經(jīng)擴(kuò)充的輸出代碼,其中所述經(jīng)擴(kuò)充的輸出代碼包括對從符合所述基于模式的交互的模式的類中繼承的專用方法的回調(diào),其中所述回調(diào)被所述編譯器插入到所述經(jīng)擴(kuò)充的源代碼中,所插入的回調(diào)包括對在所述可恢復(fù)方法暫停之前執(zhí)行的方法的調(diào)用、以及對在所述可恢復(fù)方法恢復(fù)之后執(zhí)行的方法的調(diào)用。
9.如權(quán)利要求6所述的方法,其特征在于,所述在句法上可區(qū)分的控制點(diǎn)表達(dá)被嵌套在編寫所述源代碼的編程語言的控制結(jié)構(gòu)內(nèi)。
10.如權(quán)利要求6所述的方法,其特征在于,所述可恢復(fù)方法被改寫成狀態(tài)機(jī),其中用狀態(tài)機(jī)邏輯擴(kuò)充所述可恢復(fù)方法的調(diào)用方法,并且把與所述可恢復(fù)方法相關(guān)聯(lián)的專用命令改寫成用于狀態(tài)變換和掛起的代碼。
11.一種包括當(dāng)執(zhí)行時(shí)使至少一個(gè)處理器執(zhí)行下列操作的計(jì)算機(jī)可執(zhí)行指令的計(jì)算機(jī)可讀存儲介質(zhì)接收源代碼,所述源代碼包括與模式相關(guān)聯(lián)的可恢復(fù)方法,所述可恢復(fù)方法包括在句法上可區(qū)分的控制點(diǎn)表達(dá),其中編譯器調(diào)用符合與所述可恢復(fù)方法相關(guān)聯(lián)的模式的代碼,所述代碼處于所述編譯器外部的庫中,所述編譯器從所述代碼中創(chuàng)建專用驅(qū)動(dòng)程序類; 從派生的專用驅(qū)動(dòng)程序類中實(shí)例化對象,所述對象表示包括異步方法或迭代器或?qū)ΨQ協(xié)同例程的可恢復(fù)方法。
12.如權(quán)利要求11所述的計(jì)算機(jī)可讀存儲介質(zhì),其特征在于,進(jìn)一步包括當(dāng)執(zhí)行時(shí)使所述至少一個(gè)處理器執(zhí)行下列操作的計(jì)算機(jī)可執(zhí)行指令 將專用行為和專用方法添加到來自被調(diào)用的代碼的派生的專用驅(qū)動(dòng)程序類。
13.如權(quán)利要求11所述的計(jì)算機(jī)可讀存儲介質(zhì),其特征在于,進(jìn)一步包括當(dāng)執(zhí)行時(shí)使所述至少一個(gè)處理器執(zhí)行下列操作的計(jì)算機(jī)可執(zhí)行指令 將所接收的源代碼變換成經(jīng)擴(kuò)充的源代碼,其中所述經(jīng)擴(kuò)充的源代碼包括對從被調(diào)用的代碼中繼承的專用方法的回調(diào),其中所述回調(diào)被所述編譯器插入到所述經(jīng)擴(kuò)充的輸出代碼中,所插入的回調(diào)包括對在所述可恢復(fù)方法暫停之前執(zhí)行的方法的調(diào)用、以及對在所述可恢復(fù)方法恢復(fù)之后執(zhí)行的方法的調(diào)用。
14.如權(quán)利要求10所述的計(jì)算機(jī)可讀存儲介質(zhì),其特征在于,進(jìn)一步包括當(dāng)執(zhí)行時(shí)使所述至少一個(gè)處理器執(zhí)行下列操作的計(jì)算機(jī)可執(zhí)行指令 為嵌套在編寫所接收的源代碼的編程語言的控制結(jié)構(gòu)內(nèi)的回調(diào)創(chuàng)建控制點(diǎn)。
15.如權(quán)利要求10所述的計(jì)算機(jī)可讀存儲介質(zhì),其特征在于,進(jìn)一步包括當(dāng)執(zhí)行時(shí)使所述至少一個(gè)處理器執(zhí)行下列操作的計(jì)算機(jī)可執(zhí)行指令 將包括所述可恢復(fù)方法的所接收的源代碼變換成經(jīng)擴(kuò)充的輸出代碼,使得所述經(jīng)擴(kuò)充的輸出代碼能夠在分立的部分中執(zhí)行,每個(gè)分立的部分都在所述經(jīng)擴(kuò)充的輸出代碼中的控制點(diǎn)處開始和結(jié)束。
全文摘要
提供了API,所述API處于編程語言的外部但是提供可插入到語言編譯器中的功能。所提供的API調(diào)節(jié)與使用通用基于模式的方案進(jìn)行的異步編程、迭代器或編寫對稱協(xié)同例程相關(guān)聯(lián)的功能。在API中提供了若干類型的可恢復(fù)方法,所述可恢復(fù)方法可以應(yīng)用于以傳統(tǒng)程序代碼編寫的方法主體。以傳統(tǒng)編程代碼編寫的方法主體中的在句法上可區(qū)分的控制點(diǎn)通過編譯器使用外部API來調(diào)用該代碼的變換。經(jīng)變換的代碼實(shí)現(xiàn)夾在經(jīng)變換的代碼的控制點(diǎn)之間的代碼的暫停和恢復(fù)。里面具有控制點(diǎn)的方法內(nèi)所包括的源代碼被變換為使得該方法內(nèi)的代碼可以在分立的部分中執(zhí)行,每個(gè)部分都在經(jīng)變換的代碼中的控制點(diǎn)處開始和結(jié)束。
文檔編號G06F9/45GK102859489SQ201180020904
公開日2013年1月2日 申請日期2011年4月26日 優(yōu)先權(quán)日2010年4月27日
發(fā)明者H·J·M·梅杰, M·托格森, N·M·加夫特, N·古斯塔夫松 申請人:微軟公司