专利名称::对存储器隔离许可的类型系统支持的制作方法对存储器隔离许可的类型系统支持背景用于共享存储器的多处理器的并发编程可以包括供多个线程访问相同的数据的能力。多个线程在涉及在各处理器当中共享存储器系统的多个处理器、多个处理器核或其他类别的并行硬件体系结构上执行。共享存储器模型是多线程化通信的最常见的部署方法。在这样的系统中,并发线程可以尝试访问和修改共享存储器中的相同数据,且常常使用对实际共享硬件设备上的存储器位置和输入/输出的修改来实现功能。这两种技术都有副作用。由于同时访问这些共享资源,副作用可以在并发编程中引起竞争情况和其他不期望的效果。实现并发编程中的主要困难涉及管制对这些共享资源的访问以便避免不期望的效果。开发者常常依赖于一种形式的同步来得到并发安全性。同步常常涉及锁的使用,锁是确保数据不能被同时访问的悲观并发控制机制的一种形式;这保证读取数据的线程将不会看到正被另一线程更新的状态。同步常常以性能和可扩展性为代价提供安全性。诸如那些基于乐观并发控制(例软件事务存储器)等的较新的同步技术提供了比锁优越的性能和可扩展性。但是所有现代同步机制,即使是乐观并发控制,都最终在并发编程中引起问题在线程等待另一线程时,可扩展性下降;共享存储器系统使用在各线程共享对存储器的访问时其性能显著下降的高速缓存;等等。概述提供本概述以便以简化的形式介绍将在以下的详细描述中进一步描述的一些概念。本概述并不旨在标识出所要求保护的主题的关键特征或必要特征,也不旨在用于限定所要求保护的主题的范围。用隔离许可修饰符标记对象引用,隔离许可修饰符指示该引用的什么接收者可以处置该引用指向的对象。多种许可可以被包括在一个许可集中。贯穿本公开内容使用的示例中,该集合中包括三种许可。更具体地,许可包括不可变许可、读许可和写许可。例如,不可变引用指向可能在并发线程之间共享的对象,其中通过该引用访问不改变的状态。读引用指向不存在并发写的、可能在并发线程之间共享的对象。并且,写引用指向不共享或者共享但是包括独占访问的对象。附图简述包括附图来提供了对各实施例的进一步理解,且这些附图被合并在本发明书内并构成其一部分。附图示出各实施例,并且与说明书一起用于解释本发明的原理。其他实施例和各实施例的许多预期优点将随着参考下面的详细描述进行更好的理解而得到认识。附图的元素不一定相对于彼此而缩放。相同的附图标记指代对应的类似部分。图1是示出示例计算系统的框图。图2是示出在诸如图1的计算系统等的计算系统上操作的托管环境的一个示例实施例的框图。图3是示出诸如图2的托管环境等的托管环境的方法的示例实施例的流程图。详细描述在以下具体实施例中,对附图进行了参考,附图构成了实施例的一部分且在其中作为示例示出了可在其中实践本发明的各特定实施例。就此,诸如“顶部”、“底部”、“前方”、“后方”、“前导”、“尾部”等的方向性术语参考正在描述的附图的方向来使用。因为实施例的各组件可位于多个不同的方向,所以方向性术语出于说明的目的来使用而不是限制。可以理解,可以使用其它实施例并且可以做出结构上或逻辑上的改变而不背离本发明的范围。因此,以下详细描述并不旨在限制,并且本发明的范围由所附权利要求来限定。应该理解,此处描述的各示例性实施例的特征可相互组合,除非另外具体注明。图1示出了可用作操作环境并且包括诸如计算设备100之类的计算设备的示例性计算机系统。在一基本配置中,计算设备100通常包括具有至少两个处理单元(即,处理器102)的处理器体系结构以及存储器104。取决于计算设备的确切配置和类型,存储器104可以是易失性的(如随机存取存储器(RAM))、非易失性的(诸如只读存储器(ROM)、闪存等)或两者的某种组合。该基本配置在图1中由虚线106来例示。该计算设备可采取若干形式中的一种或多种。这些形式包括个人计算机、服务器、手持式设备、消费电子产品能(诸如视频游戏控制台)或其他设备。计算设备100还可具有附加特征或功能。例如,计算设备100还可包括附加存储(可移动和/或不可移动),包括但不限于磁盘或光盘或固态存储器,或者闪速存储设备,诸如可移动存储108和不可移动存储110。计算机存储介质包括以用于存储诸如计算机可读指令、数据结构、程序模块或其他数据等的任何合适的方法或技术实现的易失性和非易失性、可移动和不可移动介质。存储器104、可移动存储108和不可移动存储110都是计算机存储介质的示例。计算机存储介质包括,但不限于,RAM、R0M、EEPR0M、闪存或其它存储器技术、CD-ROM、数字多功能盘(DVD)或其它光盘存储、磁带盒、磁带、磁盘存储或其它磁性存储设备、通用串行总线(USB)闪存驱动器、闪存卡、或能用于存储所需信息且可以由计算设备100访问的任何其它介质。任何这样的计算机存储介质都可以是计算设备100的一部分。计算设备100包括允许计算设备100与其它计算机/应用程序114通信的一个或多个通信连接115。计算设备100还可包括诸如键盘、定点设备(例如,鼠标)、笔、语音输入设备、触摸输入设备等的输入设备112。计算设备100还可包括诸如显示器、扬声器、打印机等的输出设备111。计算系统100可被配置成运行操作系统软件程序以及一个或多个软件应用程序,这些程序构成系统平台。在一个示例中,计算系统100包括被称为托管或运行时环境的软件组件。托管环境可被包括为操作系统的一部分或者可在稍后被包括为软件下载。托管环境通常包括针对常见编程问题的预先编码的解决方案以帮助软件开发者创建诸如应用等在托管环境中运行的软件程序。托管环境通常包括虚拟机,该虚拟机允许软件应用程序在托管环境中运行以使得开发者无需考虑特定处理器102的能力。运行时仅仅用作示例。然而,以下内容的实施例不被限于在托管执行环境中使用并且不被限于任何运行时需求。相反,各实施例在类型系统中实现。因此,可以构想各实施例能够在C++或其他本机代码中实现。图2示出适用于与诸如计算设备100等的计算设备操作的托管环境或运行时环境120的示例实施例。托管环境框架的特定的当前示例包括以来自美国华盛顿州雷蒙德市的微软公司的.Net和来自美国加利福尼亚州圣克拉拉市的Sim微系统有限公司的Java以及其他的商品名称销售的托管环境框架。托管环境120被配置为接受以一种或多种编程语言122的高级兼容代码编写的程序。例如,托管环境可以接受以诸如C-sharp(C#)代码124、visualbasic类型语言(例如VB.NET代码126)和Java类型语言(例如J-sharp)128等的编程语言编写的程序。编译器130被配置为编译每种兼容代码124、126、128。经编译的代码可以被提供给描述可执行代码的基础结构132和描述许多运行时的运行时环境。示例基础结构是公共语言基础结构(CLI)。该基础结构包括接收兼容语言并将它们编译成诸如公共中间语言(CIL)等的第二且平台中立中间语言的第二编译器134。中间语言被提供给诸如.NET框架中的微软公共语言运行时(CLR)等的运行时编译器136,运行时编译器136将中间语言编译成可以在当前平台或计算设备上执行的机器可读代码138。为了允许运行时向托管代码提供服务,语言编译器发出描述代码中的类型以及其他事物的元数据。绝大部分的编程语言明确地包括“数据类型”和“类型系统”的概念,但不同的语言可以包括不同的术语来描述这些特征。数据类型是描述诸如合法值集和所允许的对值的操作等关于数据的一些特征的相应数据的属性。数据类型是对应数据的元数据。类型赋予数据含义,这是因为计算设备100的硬件在存储器地址、指令代码、整数、浮点数等等之间不作区分。类型系统将一种或多种类型与每一程序值相关联,并尝试证明没有出现程序错误。这常常借助于诸如c#编译器、CLR验证器或C++编译器等的语言编译器136来验证。下面公开的示例描述用于通过类型系统的附加子集控制副作用的平台级能力。当状态被限制在线程内时,准许副作用,这准许一种形式的并发安全性而无需同步。隔离支持允许类型系统创建保持在方法调用之前存在的状态中的方法以及改变其他方法中的某些状态(作为自变量而被传送)的许可。在各示例中,可以用来自一组多个隔离许可修饰符的声明该引用的什么接收者可以处置该对象的隔离许可修饰符来标记对象引用。存在控制副作用的其他示例,但是没有一个示例涉及对个体引用执行的作用许可。作用系统试图用特定方法来分类所允许的副作用。功能性编程语言(例如Haskell)以完全不同的方式解决该问题,这是因为它们完全不允许副作用。Haskell允许使用“状态一元体(statemonad)”来模拟副作用一与普通函数调用和语句完全不同地建模,且常常与do组合器组合起来。这提供了命令性编程风格的错觉,但它是用函数一元体和延拓来低效地和笨拙地建模的。不同于上面提供的Haskell示例,所公开的示例对诸如C++、C#和Java等的命令性编程语言起作用。命令性编程是将计算描述为改变程序状态的一系列语句的计算机编程范例,更直接地建模了传统的vonNeumarm(冯·诺依曼)体系结构的真实能力。命令性编程可以是与功能性编程形成对比,功能性编程避免状态和可变数据。例如,纯函数程序不具有副作用,副作用是在返回值的同时对某种状态的修改。另一方面,纯函数程序可以不做任何事情,这是因为,没有副作用,程序就不接受输入、不产生输出并且不与外部设备对接。命令性编程使用副作用来实现状态和输入/输出功能。本公开内容的一般示例包括状态隔离和通过类型许可保持状态隔离的方法的定义。图3示出可以被实现为诸如计算设备100上的运行时环境或托管框架等的语言编译器的一部分的方法300的示例实施例。方法300包括在302定义用于控制通过指向对象的引用访问成员的多个类型修饰符。在304,将类型修饰符中的一个与每一类型名称相关联。代替只是列出〈类型名称〉,系统提供〈类型名称,修饰符〉的元组,其中“修饰符”可以是许可。在306,定义多个类型修饰符的一个方面包括定义限制对该对象的操作的不同访问许可。在与类型或隔离方法一起使用时,类型许可限制可以对它所指向的对象关系图做什么。在308,类型许可包括诸如“不可变”和“可变”等的至少两个隔离修饰符,以便控制通过引用对各成员的访问。当然,多于两个的修饰符是可能的。在一个示例中,在310,使用了三个隔离修饰符,包括“不可变”、“读”和“写”(也构想多于三个的隔离修饰符,以便限制可以对各对象做什么)。不可变引用指向可能在各并发线程当中共享的对象,但静态地保证可通过该修饰符访问的状态永不改变。读引用也指向可能在各并发线程当中共享的对象,但在读引用存在的同时不准许并发写。在一个示例中,这可以包括不可变的访问以及对可变字段的读取。写引用指向不同时与另一线程共享的对象或具有独占访问的共享对象,以使得可以由这样的引用的持有者安全地进行写。不可变-读-写许可的更具体示例包括只不可变、只读和读-写。只不可变(i)许可只可以用来从不可变的成员读取。可以跨越各线程自由共享和并发访问该对象,且该对象将不引起并发性问题。只读(r)许可可以被用来从任何成员读取,包括可变字段。该对象可以不被共享,或者可以存在某种形式的并发安全性以便允许并发读取。例如,可以由线程保持读锁或者某种对引用的静态控制将使得成员避免并发写。或者,带有读-写(w)许可的对象可以跨越带有结构化数据并行构造的叉接屏障而作为只读(r)共享。读-写(w)许可可以被用来写任何成员,且可以包括带有可变字段的成员。存在某种形式的并发安全性以便允许写。例如,可以持有独占锁,或者将对象限制在单个线程内。隔离许可可以利用以命令性编程语言(例如在J.Duffy和A.Hejlsberg的标题为“ImmutableTypesinImperativeLanguage(命令性语言中的不可变的类型)”的美国专利申请第12/163,868号中描述的命令性编程语言)的不可变的字段或单次赋值的值。正如所描述的,不可变的类型是其中构造后的改变是不可能的类型。被用来以命令性语言建立不可变类型的一个示例是创建对“initonly(只初始化),,字段的支持。hitonly指示变量赋值只可以作为声明的一部分而出现或者在相同的类中的中的静态构造函数中出现。hitonly字段是一旦已经完全构造该字段驻留在其上的对象就不能写的字段。在这一上下文中,完全构造意味着该对象的构造函数已经完成执行。命令性语言可以包括例如借助于公共语言运行时验证这一性质的类型系统支持并且拒绝不遵守各规则的程序。支持initonly字段的示例包括C#编程语言中的“readonly(只读)”。类型“T”的每次出现可以以许多种方式与这些修饰符中的一个相关联。在一个示例中,使用记法T:X,其中χ是隔离修饰符中的一个。在三个隔离修饰符的示例中,χ可以是i=只不可变,r=只读,且W=读-写。为简单起见,贯穿本公开内容使用示例记法T:X,但是构想可以使用其他记法。程序可以在其中要命名类型的任何上下文中指定隔离修饰符。在通用句法(即,不考虑任何具体的编程语言)中使用记法Τ:Χ的示例包括形式参数声明=VOidf(T:xfoo){···}·局部变量声明voidf(){T:xfoo;...}字段(状态或实例)声明:classC{privateT:xm_foo;...}类属型参数:classC<T>{··.}voidf(){C<T:x>foo;…}以及其他。也这样表示数组,例如T:x[]:y。可以以许多方式来实现上面的示例,在这里指出其中的一些方式。在一种实现中,默认的访问修饰符是不可变或只不可变(i),以使得未加修饰的类型T等效于T:i。应注意,隔离区域映射到程序作用域,然而,在一些实现中,在隔离区域外的程序代码可以忽略许可注释。这可以用于拓宽隔离许可的应用,并且提供对现有代码传统友好的运行时。在一种实现中,类型T的静态变量是“T:i”,这是因为各静态变量被共享。在按值传送中,编译器将调用函数中的自变量的值复制到被调用的函数定义中相应的非指针或非引用参数。用所传递的自变量的值来初始化被调用的函数中的参数。只要参数不被声明为常量,就可以改变参数的值。但是,仅在被调用的函数的作用域内执行改变。改变不影响调用函数中的自变量的值。其他实现包括使用中间语言(IL)关键字来返回带有读-写许可的对象。例如,"newobjΤ”关键字返回具有类型“T:w”的对象。“newarrΤ”关键字返回具有类型“Τ[]w”的对象。在一种实现中,许可是加性的。例如,写(w)隐含读(r),且读(r)隐含不可变(i)。换言之,T:w是实际上等效于T:irw,且T:r实际上等效于T:ir。因而,可以安全地移除许可,其中T:w隐式地强制为T:r,且T:r隐式地强制为T:i。因而,(w)可以被认为是比(r)更强的许可,或者(r)比(w)更弱。借助于隔离许可,可以将并发安全性扩展到带有“隔离”方法修饰符的方法,“隔离”方法修饰符指示隔离方法考虑隔离许可。在一个示例中,隔离方法“M”的代码遵循隔离许可。例如,对于(i)引用,不可以对类型中的可变字段进行读或写,且对于(r)引用,不可以写类型中的可变字段。在一些示例中,M将不调用非隔离方法或非隔离委托。在方法或委托调用期间,M提供具有与实际输入参数的相应形式参数相同的或更强的许可的实际输入参数。在方法和委托调用期间,M提供具有与相应的形式参数相同的许可的实际输出(byref)参数,这是因为byref可以被用于读取和存储。M存储与目标存储位置类型访问兼容的引用,例如,如果存储位置具有与源引用相同的或较弱的许可。进一步,在M盖写虚方法或实现接口方法时,(1)所有输入(非byref)参数具有与成员声明形式相同的或较弱的许可;(所有byref参数具有相同的隔离修饰符,以及(返回类型包括与成员声明的返回类型的许可修饰符相同的或更强的许可修饰符。借助于这些规则,M不揭示可能违反隔离许可的引用,且由此访问许可对整个方法调用关系图保持有效。下列伪代码被用作说明classC{privateT:wm—f;publicC(){m—f=newT();}publicisolated:rT:rGet(){returnm_f;}publicisolated:wvoidSet(T:wobj){m_f=obj;}}字段m_f用T:w许可标记,且经由具有T:w许可的“Set”方法对象接收和存储。内部对象的任何展示都经由“Get”方法借助于T:r许可进行,且这是可能的,因为T:w隐式地强制为T:r。“isolated:^的记法约定被用来指示该方法的隐藏的“this”自变量具有许可X,因此在该示例中“Get”以“this:r”操作且“Set”以“this:w”操作。非隔离方法可以忽略访问修饰符。非隔离代码和隔离代码的边界处的代码强制不加修饰的“T”引用,以使得它们包括适当的许可修饰符。“isolated”委托类型“D”绑定到“isolated”方法“M”,其中输入参数和输出参数与委托参数是访问兼容的。建立隔离委托类似于(但相反)如上所述的盖写虚方法和实现接口方法。更具体地,输入(非byref)参数可以强于目标的参数,byref参数匹配许可,且返回类型参数可以弱于目标的参数。例如,给定方法“isolatedvoidM(C:rc)”,评估下列委托类型是否合法绑定到该方法isolateddelegatevoidA(C:wc);/7¢554^0^を夕去。isolateddelegatevoidB(C:rc);//在精确时合法。isolateddelegatevoidC(C:ic);//在弱化时合法。类属也能够遵守修饰符。例如,考虑类属委托“isolateddelegateUIsolatedFunc<T,U>(Te);”,“T”和“U”的实际參数确定可以将它本身绑定到的各方法示例1isolatedstaticC:rM(C:rc);...IsolatedFunc<C:r,C:r>a=M-J/在精确时合法。IsolatedFunc<C:w,C:r>b=M;//在强化输入(协方差)时合法。IsolatedFunc<C:r,C:i>c=M-J/在弱化输出(逆方差)时合法。IsolatedFunc<C:w,C:i>c=M-J/对两者都合法示例2isolatedstaticC:rM(C:rc);...IsolatedFunc<C:i,C:w>c=M;//在协方差和逆方差是相反时非法。类似于上面提到的方法的盖写,向语言作者提供关于是否支持协方差和逆方差的决定。在成员访问期间,将所包含的表达式类型的许可与该成员的所声明的访问许可组合在一起。例如,给定成员访问“ο.M”,其中“0”是类型“T:X”的引用且“M”具有所声明的类型“U:y”,则语句“ο.Μ”的类型将是U:min(X,y),其中所得到的引用不强于该组合的最弱许可。换言之,给定Tχ引用,从方法Uy返回的任何字段Uy或值变形为Umin(χ,y),例如{T:w+U:r}=U:r{T:r+U:w}=U:r{T:w+U:w}=U:w这些规则规定被授权给单个引用的许可将也适用于该引用可达到的对象关系图。对于“Customer(消费者)”类型的示例classCustomer{puplicOrder:w_order=}以及来自读访问的上下文的实例Customer:rc=...;这些规则规定不允许对order的写c._order._total=...-J/错误_order被擦除成Orderir而不是Orderiw在另一示例中,系统容许抑制对代码区域的检查以便允许优选的副作用的能力。对各字段的byref(byref)——例如“out”和“ref”参数——与所得到的类型将变成U&:min(X,y)而不是U:min(x,y)的异常相似。这一实例中的“&”意味着“对‘U’[引用]的引用”。借助于通过经由byref访问值类型字段来避免复制的一般惯例,这一byref规则保护免于可能的特权提升。系统还包括约束类属型参数的能力。例如,在其中System.Object包含方法'voidisolated:rEquals(object:rother)'的情况中。如果写出检查两个对象是否相等的ListCD类(也许作为实现'boolisolated:rContains(object:robj)‘方法的一部分),则它声明T至少是可读的,这可以导致Timmutab1e(不可变)Timmutab1e+(不可变+)Treadable-(可读_)Treadable(可读)Treadable+(可读+)Twritable-(可写_)T:writable(可写)尽管此处说明并描述了具体实施例,但本领域技术人员可以理解,可用各种替换和/或等价实现来替换所示出并描述的具体实施例而不背离本发明的范围。本申请旨在覆盖此处讨论的具体实施例的任何改编或变型。因此,本发明旨在仅由权利要求书及其等效方案来限制。权利要求1.一种存储用于控制计算设备执行一种方法的计算机可执行指令的计算机可读存储介质,所述方法包括定义用于控制通过指向对象的引用访问类型成员的多个类型修饰符302;以及对于类型名称的每次出现,关联所述多个类型修饰符中的一个304,其中所述多个类型修饰符中的每一个定义不同的访问许可以便限制对所述引用指向的所述对象的操作306。2.如权利要求1所述的计算机可读存储介质,其特征在于,所述方法在类型的上下文中指定所述类型修饰符。3.如权利要求1所述的计算机可读存储介质,其特征在于,所述受支持的许可包括不可变许可,其中不可变引用指向可能在各并发线程之间共享的对象,其中通过所述引用访问不改变的状态;读许可,其中读引用指向不存在并发写的、可能在各并发线程之间共享的对象;以及写许可,其中写引用指向作为不共享或者共享但包括独占访问的对象的对象。4.如权利要求3所述的计算机可读存储介质,其特征在于,单次赋值的值通过不可变许可访问。5.如权利要求3所述的计算机可读存储介质,其特征在于,读引用隐含不可变访问且允许可变字段的读取。6.如权利要求3所述的计算机可读存储介质,其特征在于,对所述引用的写能够以安全并发完成。7.如权利要求1所述的计算机可读存储介质,包括组合所述访问许可以便用根引用的所述访问许可保护对象关系图。8.如权利要求8所述的计算机可读存储介质,其特征在于,从所述组合所得到的所述引用将不强于所述组合的最弱许可。9.一种系统,包括计算设备100;以及可操作上被耦合到所述计算设备100的命令性框架,其中所述命令性框架包括被配置为控制通过指向对象的引用访问类型成员的多个类型修饰符302;其中所述多个类型修饰符中的一个与类型名称的每次出现相关联304;并且其中所述多个类型修饰符中的每一个定义不同的访问许可以便限制对所述引用指向的所对象的操作306。10.如权利要求9所述的系统,其特征在于,所述访问许可包括不可变许可,其中不可变引用指向可能在各并发线程之间共享的对象,其中通过所述对象访问不改变的状态;读许可,其中读引用指向不存在并发写的、可能在各并发线程之间共享的对象;以及写许可,其中写引用指向作为不共享或者共享但包括独占访问的对象的对象。11.如权利要求10所述的系统,其特征在于,所述不可变许可与不可变字段相关联。12.如权利要求10所述的方法,其特征在于,所述读许可与读锁相关联。13.如权利要求10所述的系统,其特征在于,所述写许可与独占锁相关联。14.如权利要求9所述的系统,其特征在于,所述类型修饰符在类型的上下文中指定。15.如权利要求9所述的系统,其特征在于,所述命令性框架包括用所述访问许可定义的隔离区域和在所述隔离区域之外的另一区域,其中所述隔离区域映射到程序作用域,并且其中所述另一区域被配置为选择性地忽略访问许可。全文摘要用隔离许可修饰符标记对象引用。可以包括至少两种许可,且在示例中包括三种许可。在实现各许可时,定义用于控制通过指向对象的引用访问类型成员的类型修饰符。类型修饰符中的一个与类型名称的每次出现相关联。类型修饰符中的每一个定义不同的访问许可以便限制对引用指向的对象的操作。文档编号G06F12/14GK102395979SQ201080017093公开日2012年3月28日申请日期2010年4月1日优先权日2009年4月13日发明者A·赫杰斯伯格,J·J·达菲,M·塔耶费尔,S·E·卢科申请人:微软公司