Asynchronous enumerable objects generated by the compiler
By generating a single asynchronous enumerable object, using the waitable and waiter object to suspend and restore iterative state in the asynchronous enumeration, the problem of excessive memory consumption in asynchronous enumeration is solved, and the program's responsiveness and performance are improved.
Patent Information
- Application Number
- CN201980014315.2
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Priority Date
- 2018-02-28
- Filing Date
- 2019-02-18
- Publication Date
- 2025-01-07
- Estimated Expiration
- 2039-02-18
AI Technical Summary
In the prior art, when asynchronous enumeration is asynchronous, memory consumption caused by the storage and recovery of iterative states is too large, which affects the responsiveness and performance of the program.
By generating a single asynchronous enumerable object, containing the data and methods required for asynchronous iteration, the wait and waiter object suspends and restores iteration state in iterations, reducing memory consumption.
Reduces memory consumption of asynchronous enumerations, improves program responsiveness and performance, and reduces the overhead of heap allocation and garbage collection through single object reuse.
Smart Images

Figure CN111771186B_ABST
Abstract
Description
Background Art
[0001] The iterator design pattern proposes a method for object-oriented programming languages to iterate over a collection or sequence of data without exposing the structure of the data. The pattern separates the structure of the data (i.e., a collection, sequence, etc.) from the logic used to traverse the data, which is beneficial when the structure is unknown, such as when retrieving data over a network or manufacturing data on demand. In this way, the developer (i.e., programmer, user, etc.) does not have to track the number of elements in the collection, the number of elements that have been traversed, and the number of elements remaining in the collection during traversal. Instead, the iterator design pattern uses an iterator object to access the elements of a collection. Different object-oriented programming languages implement the iterator design pattern with a specific interface that defines how to access and traverse a collection using an iterator object.
[0002] A program may include an iterator block that contains one or more source code statements that iterate over a collection of data such as an array, a list, a string, etc. An iterator block may include a wait statement that suspends processing in an iteration until the asynchronous operation is completed. At this point, the state of the iteration is saved to resume its execution at a recovery point when the asynchronous operation is completed. The state data at each iteration may be stored in a separate dynamically allocated object on the heap, which results in a huge cost for dynamic allocation and for garbage collection processes for reclaiming the object when the state data is no longer used by the program. This overhead may be considerable and therefore may have an adverse effect on the responsiveness and performance of the program. Summary of the invention
[0003] This summary is provided to introduce some concepts in a simplified form, which are further described in the detailed description below. This summary is not intended to identify key features or essential features of the claimed subject matter, nor is it intended to be used to limit the scope of the claimed subject matter.
[0004] Generates a single asynchronous enumerable object that contains the data and methods needed to iterate the enumerable asynchronously. The asynchronous enumerable object contains the code for traversing the enumerable one step at a time and the operations needed to suspend iteration to wait for completion of asynchronous operations and resume the iteration after completion of asynchronous operations. Allocating a single object to perform all of these tasks reduces the memory consumption required to perform asynchronous enumeration.
[0005] These and other features and advantages will be apparent from a reading of the following detailed description and a review of the associated drawings.It is to be understood that both the foregoing general description and the following detailed description are explanatory only and are not restrictive of the aspects as claimed. BRIEF DESCRIPTION OF THE DRAWINGS
[0006] Figure 1 An exemplary system for generating an asynchronous enumerable object for an asynchronous enumerable is shown.
[0007] FIG. 2A to FIG. 2B The conversion of user source code that defines an asynchronous enumerable into a compiler-generated class that represents the asynchronous enumerable, and the conversion of user source code that defines an asynchronous enumeration into compiler-generated code that implements the asynchronous enumeration are shown.
[0008] Figure 3 is a flow chart illustrating an exemplary method for generating a compiler for an asynchronous enumerable class and code for implementing an asynchronous enumeration.
[0009] Figure 4 is a flow chart illustrating an exemplary method for performing asynchronous enumeration.
[0010] FIG. 5A to FIG. 5B Exemplary methods for asynchronously and synchronously moving to the next state of an iteration are shown.
[0011] Figure 6 is a block diagram illustrating a first operating environment.
[0012] Figure 7 is a block diagram illustrating a second operating environment.
[0013] Figure 8 is a block diagram illustrating a third operating environment. DETAILED DESCRIPTION
[0014] Overview
[0015] The disclosed subject matter relates to techniques for reducing the amount of runtime support and memory consumption used to facilitate processing of asynchronous enumerables. An asynchronous enumerable is a collection or sequence of data that can be enumerated asynchronously. Enumeration of an asynchronous enumerable requires waiting for the completion of zero or more asynchronous operations within an iteration. The techniques disclosed herein process an asynchronous enumerable using a single asynchronous enumerable object that contains the data, protocol, and operations required to perform the asynchronous enumeration.
[0016] The disclosed subject matter is described with respect to implementing asynchronous enumerables in a programming language (e.g., C#, F#, Visual Basic) supported by the .NET Framework. The .NET Framework is a code execution environment that supports object-oriented programming through a set of tools that enable the development and execution of software programs that run in Windows-based operating systems. However, it should be understood that the disclosed subject matter is not limited to this particular implementation, and the disclosed techniques are applicable to other implementations of asynchronous and / or parallel programming environments.
[0017] An enumerable is a collection or sequence of data that can be accessed iteratively, such as an array, string, or list. An enumerator is an object that facilitates traversing a collection one element at a time. An enumerator allows the user to process each element in an enumerable without having to know the number of elements in the enumerable and the structure of the enumerable. An enumerator can also act as a cursor pointing to the current element of a collection or enumerable.
[0018] The following code snippet represents an asynchronous enumerable
[0019]
[0020] In each iteration, there is an await statement that suspends processing for a period of time defined by the time delay Task.Delay(i*1000) before returning the value of i via yield return i. Lines 14-22 of the pseudocode quoted above contain a loop that iterates each await and yield statement a number of times defined by the variable items. The await statement causes processing to be suspended until the delay has completed. The state of the iteration or enumeration is saved at the suspension point, and the iteration resumes after the completion of the asynchronous operation defined in the await statement.
[0021] In order to suspend the execution of the enumeration at a suspension point, the state of the iteration and the resume point will need to be saved on the heap until the completion of the operation associated with the await statement. This will cause objects to be dynamically allocated on each enumeration of the loop, thereby increasing the memory consumption caused by asynchronous enumeration. The technology described herein reduces this overhead by utilizing a single asynchronous enumerable object that stores the data, protocols, and methods required to facilitate enumeration through the asynchronous enumerable.
[0022] To execute an await statement, the compiler generates the code necessary to perform the operations that support the await statement, which includes saving the state of the iteration at the suspension point, determining when the asynchronous operation has completed, and resuming execution of the iteration at the resume point. This is more particularly illustrated with respect to the following pseudocode segment.
[0023] The CountAsync() asynchronous enumerable is consumed by the following pseudo code:
[0024]
[0025] In the pseudocode above, the foreach statement calls CountAsync() once. The CountAsync() method returns the enumerable being enumerated, and the body of the loop calls Console.WriteLine() the number of times defined by the variable items. Code that consumes an asynchronous enumerable is considered an asynchronous enumerator.
[0026] To suspend iterations to wait for the completion of an asynchronous operation, the techniques described in this article use awaitables and awaiters. An awaitable is an object that contains a method GetAwaiter(). The GetAwaiter() method sets an awaiter to wait for the completion of an asynchronous operation. The awaiter provides notification when the await expression has completed. The awaiter contains methods that implement the OnCompleted method, the GetResult method, and the IsCompleted property, all of which are used to check whether the asynchronous operation has completed, to set the state machine to a resume point when the asynchronous operation completes, and to obtain the results associated with the completion of the asynchronous operation.
[0027] In C#, there are several interfaces that are used to facilitate asynchronously iterating or enumerating a collection of data. An interface contains only method signatures, properties, events, and indexers. A class or structure that implements an interface must implement the members of the interface. The compiler in C# generates implementations for interfaces that are contained in asynchronous enumerable objects.
[0028] In one aspect, there is IAsyncEnumerable <t>An interface that exposes an enumerable that is a collection that can be enumerated asynchronously and a protocol that is used to enumerate asynchronous enumerables. <t>The interface contains the GetEnumerator method, which gets a specific enumerator or iterator of an enumerable that is used to traverse the enumerable.
[0029] IAsyncEnumerator <t>The interface facilitates traversal of the collection by exposing the Current property and the MoveNextAsync method. The Current property indicates the element in the collection at the current enumerator. The MoveNextAsync method advances the enumerator to the next element in the collection. The first call to the MoveNextAsync method causes the enumerator to move to the first element in the collection. When the MoveNextAsync method passes the end of the collection, the MoveNextAsync method returns false, and the enumerator is positioned after the last element in the collection. The MoveNextAsync method returns true when there is another element in the collection. The MoveNextAsync method returns an awaitable that provides notification when the asynchronous operation completes.
[0030] IAwaitable <t>The interface exposes the GetAwaiter method. The GetAwaiter method creates a waiter, which is of type IAwaitable <t>Instance of type IAwaitable <t>Exposes the ICriticalNotifyCompletion interface, IsCompleted property, and GetResult method. The ICriticalNotifyCompletion interface exposes the OnCompleted method for hooking up continuation at a continuation point or a resume point, the IsCompleted property returns a Boolean value indicating whether the asynchronous operation has completed processing, and the GetResult method obtains the result of the asynchronous operation.
[0031] A single asynchronous enumerable object implements IAsyncEnumerable <t>、IAsyncEnumerator <t>、IAwaiter <t>and IAwaitable <t>interface, thereby playing the role of enumerator, enumerable, awaitable, and awaiter. In this way, there is a single allocation of this object for all iterations of the asynchronous enumerable.
[0032] Due to the complexity of the implementation required to perform an asynchronous enumeration, the compiler converts source code representing an asynchronous enumerable into a class that contains the implementation of the interface, methods, state machine, and local data required to enumerate the asynchronous enumerable.
[0033] Attention now turns to a more detailed description of techniques, methods, systems, and devices that facilitate asynchronous enumerables through the use of asynchronous enumerable objects.
[0034] Compiler-generated asynchronous enumerable objects
[0035] Figure 1 A block diagram of an exemplary system 100 for facilitating enumeration of an asynchronous enumerable by using an asynchronous enumerable object is shown. The system 100 includes a source code program 102 that is input to a compiler 104. The compiler 104 converts the source code program 102 into executable code 106. In the compilation, the compiler 104 converts a portion of the source code program 102 that represents an asynchronous enumerable 112 into a compiler-generated class 116 for the asynchronous enumerable. The compiler 104 also converts a portion of the source code 102 that represents an asynchronous enumerable 110 into compiler-generated code 114 that implements the asynchronous enumerable that performs the operations required to execute the asynchronous enumerable 110.
[0036] When the compiler-generated code 106 is executed, the runtime 108 allocates a single asynchronous enumerable object 118 to facilitate asynchronous enumeration based on the compiler-generated class 116 for the asynchronous enumerable. For each iteration 120 of a particular asynchronous enumerable, the single asynchronous enumerable object 110 represents the enumerable 122, the enumerator 124, the awaitable 126, and the awaiter 128.
[0037] Executable code 106 may be managed code compiled to execute under runtime 108, or native code compiled to execute on a specific processor. In the case of the .NET Framework, the program is compiled into an intermediate representation in a platform-neutral language called Common Intermediate Language (CIL) and provided to Common Language Runtime (CLR) 108, which compiles the intermediate representation into processor-specific machine or executable code 106 at runtime. In other managed environments or implementations, the intermediate representation is executed using an interpreter or a combination of an interpreter and a runtime environment.
[0038] In one aspect, compiler 104 is a language compiler. A language compiler operates on source code of a program written in a particular programming language. A language compiler parses the source code according to the syntax of the underlying programming language. A language compiler can generate executable code, whether native code or managed code (i.e., intermediate representation, bytecode, etc.).
[0039] although Figure 1 The system 100 shown in FIG. 1 has a limited number of elements in a certain configuration, but it should be understood that in alternative configurations, the system 100 may include more or fewer elements. The embodiments are not limited in this manner. For example, the system 100 may include an integrated development environment (IDE) (e.g., Microsoft's Visual NetBeans, Eclipse, SharpDevelop, Lazarus, etc.), which provides a set of software development tools, such as compilers, source code editors, analyzers, debuggers, linkers, binders, etc., which are conducive to generating executable code with asynchronous programming support.
[0040] Now attention turns to FIG. 2A to FIG. 2B , which illustrates the compiler's conversion process 200 with exemplary pseudo code. It should be noted that the pseudo code attached hereto is for illustrative purposes and should not be interpreted as limiting the subject matter to a specific implementation. It should also be noted that when the converted instructions are executed on the processor, these instructions implement a method for performing the actions of the converted instructions.
[0041] Source code program 201 includes an asynchronous enumerable CountAsync() 204, which is consumed by an asynchronous enumerator 202. During compilation of source code program 201, the compiler converts asynchronous enumerator 202 into the code shown in block 206. The code statement at line 10 IAsyncEnumerable <int>enumerable = CountAsync (items) identifies the CountAsync () type of IAsyncEnumerable and sets the variable enumerable to the method CountAsync (). The code statement at line 11 is IAsyncEnumerator <int>enumerator = enumerator.GetEnumerator() calls the GetEnumerator() method, which returns the current iteration of the CountAsync() enumerable.
[0042] The while loop at lines 14-22 iterates over each element of the enumerable CountAsync(). When the awaited operation has completed, the MoveNextAsync() method moves the state machine to the next element in CountAsync(). The call to MoveNextAsync() returns an awaitable that represents true, false, or an asynchronous enumerable object. In line 17, if (await awaitable) produces true, the asynchronous operation has completed, and the process proceeds to lines 19-20, where Current returns the current value of i, which is output via Console.WriteLine(i). If (await awaitable) produces false, there are no more elements in the enumerable, and the state machine proceeds to lines 24-27, which handle the task of performing the asynchronous enumeration. If the call to MoveNextAsync() returns an awaitable that represents an operation that has not yet been completed, the process waits for notification of the completion of the asynchronous operation.
[0043] Figure 2B The conversion of the if (await awaitable) statement (line 17 in pseudocode 206) to the converted code 302 is shown. The statement in line 30, var awaiter = awaitable.GetAwaiter() calls the awaitable GetAwaiter method to create the awaiter. If the awaiter has not completed processing if (! awaiter.IsCompleted), the OnCompleted method is called in line 36, which sets the continuation at the recovery point. If the awaiter has completed processing, processing proceeds to line 44Label42, where the GetResult method is called. The GetResult method obtains the result from the asynchronous operation.
[0044] Return to Figure 2A The compiler also generates a class to represent an asynchronous (async) enumerable 204. The compiler-generated class 208 for an asynchronous enumerable includes a state machine 210, local data 212 associated with the iteration, and a state machine 210 for IAsyncEnumerable. <t>214 interface method implementation, used for IAsyncEnuerator <t>216 interface method implementation, used for IAwait <t>218 interface structure implementation and use for IAwaitable <t>220 interface structure implementation.
[0045] Attention is now directed to the description of various exemplary methods utilizing the systems and devices disclosed herein. The operation of various aspects may be further described with reference to the various exemplary methods. It should be understood that, unless otherwise specified, these methods are not necessarily performed in the order presented or in any particular order. In addition, the various activities described with respect to the methods may be performed in a serial or parallel manner or in any combination of serial and parallel operations. In one or more aspects, the methods illustrate the operation for the systems and devices disclosed herein.
[0046] Go to Figure 3 , which shows an exemplary method 300 for converting a user's source code into code that performs an asynchronous enumeration. The compiler parses source code statements in the program (block 302). When the compiler recognizes an asynchronous enumerable, the compiler generates a class to represent the asynchronous enumerable and the methods required to handle the asynchronous enumerable (block 304). In one aspect, an asynchronous enumerable can be defined by a class with type IAsyncEnumerable <t>The code segment is identified by the statement.
[0047] During compilation of the source code program, when the compiler identifies an asynchronous enumerable, the compiler generates a class for the enumerable (block 306). Figure 2A In one aspect shown, class 208 includes state machine 210, local data 212, and a method for IAsyncEnumerable <t>214、IAsyncEnumerator <t>216、IAwait <t>218 and IAwaitable <t>Implementation of 220 interface.
[0048] The state machine 210 is used to model the control flow of an asynchronous enumerable. The state machine structure 210 stores the code of the asynchronous enumerable, the state of the asynchronous enumerable, and the state of the asynchronous enumerable includes at least the local variables and parameters used to process the asynchronous enumerable and the methods that facilitate the conversion between the asynchronous enumerable and the asynchronous operation.
[0049] Upon completion of compilation, the compiler outputs the asynchronous enumerable class and the compiler-generated code into a format suitable as executable code (block 308).
[0050] The compiler recognizes synchronous iterators and their methods returning an enumerable with the yield keyword in an iterator block. The compiler recognizes asynchronous iterators and their methods returning an asynchronous enumerable in an iterator block with the yield keyword. An iterator block can contain the await keyword. The compiler converts the user's source code containing an asynchronous enumerable into compiler-generated source code that implements the protocol for iterating over an enumerable, suspending execution of the iteration at a suspension point, and resuming execution at a resume point.
[0051] Now attention turns to the runtime execution of asynchronous enumerations. Figure 4 , when the executable code is running, the runtime creates an asynchronous enumerable object from an instantiation of the asynchronous enumerable class (block 402). When a statement defining an enumerable of type IAsynEnumerable is encountered, such as Figure 2A and Figure 2B Statement 10 in box 206 - IAsynEnumerable <int>enumerable = CountAsync(items), the runtime creates an asynchronous enumerable object.
[0052] The asynchronous enumerable object contains a method GetAsyncEnumerator(), which is called for a specific enumerable to obtain an enumerator for the enumerable (box 404). Once the enumerator is obtained, the process attempts to traverse the enumerable by calling the MoveNextAsync() method on the enumerable (box 406).
[0053] Go to FIG. 5A to FIG. 5B , which shows exemplary steps used in the MoveNextAsync method. When the MoveNextAsync method is called (step 502), the method performs one of several possible actions (switch block 504). The method can synchronously determine that at least one element remains in the asynchronous enumerable (block 506), synchronously determine that no more elements remain in the asynchronous (block 508), or determine that an asynchronous continuation is necessary (block 510).
[0054] In the case where there is at least one element remaining in the asynchronous enumerable (block 506), the state machine is moved to perform an iteration of the asynchronous enumerable with the next element (block 512), and a value of true is returned to the caller of the MoveNextAsync method (block 514). In the case where there are no more elements remaining (block 508), the MoveNextAsync method returns a value of false to the caller of the MoveNextAsync method (block 516).
[0055] In the event that the process must wait for the completion of an asynchronous operation (block 510), the method can proceed in two different directions (switch block 518). If the MoveNextAsync method is notified of the completion of the awaiter (block 520), the method calls GetResult (block 522) to obtain the result of the asynchronous operation (block 522). The method then proceeds to call Continue at the resume point and returns a value of true to the caller of the MoveNextAsync method (block 522).
[0056] In the event that the process has not been notified of the completion of the awaiter (frame 524), the method calls the GetAwaiter method to create an awaiter for the operation of the await statement (frame 530). The method calls the IsCompleted method to determine whether the awaiter has completed processing (frame 532). If the asynchronous operation has completed processing (frame 534-yes), the method calls GetResult to obtain the result and returns a value of true to the caller of the MoveNextAsync method (frame 536). In the event that the asynchronous operation has not yet completed processing (frame 534-no), the MoveNextAsync method calls the OnCompleted method to continue to hang on to the recovery point, which is the callback to the MoveNextAsync method (frame 538).
[0057] Technical Effects
[0058] Various aspects of the subject matter disclosed herein relate to the technical problem of implementing an asynchronous enumeration with reduced memory consumption. A technical feature associated with solving the problem is to merge the data elements and operations required to enumerate an asynchronous enumerable into a single asynchronous enumerable object. The asynchronous enumerable object is reused at each iteration of the asynchronous enumerable to perform the roles of enumerator, enumerable, waiter, and waitable. In this way, the implementation of an asynchronous enumeration requires a single heap allocation for each iteration of the asynchronous enumerable.
[0059] Exemplary Operating Environment
[0060] Attention now turns to a discussion of an exemplary operating environment. Figure 6 An exemplary operating environment 600 is shown, which includes an integrated development environment (IDE) 602 and a common language runtime environment 604 that are communicatively coupled via a communication framework 606. IDE 602 can allow a user (e.g., a developer, a programmer, a designer, a coder, etc.) to design, code, compile, test, run, edit, debug, or build programs, assemblies, web sites, web applications, and web services in a computer system. Software programs may include source code 612, which is created in one or more source code languages (e.g., Visual Basic, Visual J#, C++. C#, J#, Java Script, APL, COBOL, Pascal, Eiffel, Haskell, ML, Oberon, Perl, Python, Scheme, Smalltalk, etc.). IDE 602 can provide a native code development environment, or can provide managed code development running on a virtual machine, or can provide a combination of both. IDE 602 can provide a managed code development environment using the .NET framework.
[0061] The user can create and / or edit source code 612 via a user interface 608 and a source code editor 610 in the IDE 602 according to known software programming techniques and specific logic and grammatical rules associated with a particular source language. Thereafter, the source code 612 can be compiled via a front-end or language compiler 614. During the compilation process, the front-end compiler 614 generates instructions that provide runtime support for the execution of asynchronous enumerables. The front-end compiler 614 generates an intermediate language representation of the source code 612, such as an assembly 616. The assembly 616 may include an intermediate language component 620 and metadata 618.
[0062] When the application is executed, an intermediate language (IL) component 620 can be created from the source code component 612 and the front-end compiler 614, and an executable code 624 (e.g., machine executable instructions) can be created from the intermediate language component 620 using a just-in-time (JIT) compiler 622. As described herein, the executable code 624 includes compiler-generated code 626 and compiler-generated classes 628. When the IL application is executed, it is compiled into a suitable machine language for the platform on which it is executed while being executed, thereby making the code portable across several platforms. In addition, in other embodiments, the program can be compiled into a native code machine language suitable for its intended platform (not shown).
[0063] Go to Figure 7 , these aspects can be applied to a second operating environment 700 utilizing at least one computing device 702. The computing device 702 can be any type of electronic device, such as, but not limited to, a mobile device, a personal digital assistant, a mobile computing device, a smart phone, a cellular phone, a handheld computer, a server, a server array or server farm, a web server, a network server, a blade server, an Internet server, a workstation, a microcomputer, a mainframe computer, a supercomputer, a network appliance, a web appliance, a distributed computing system, a multiprocessor system, or a combination thereof. The operating environment 700 can be configured in a network environment, a distributed environment, a multiprocessor environment, or a stand-alone computing device that can access a remote or local storage device.
[0064] The computing device 702 may include one or more processors 704, a communication interface 706, one or more storage devices 708, one or more input devices 710, one or more output devices 714, and a memory 712. The processor 704 may be any commercially available or custom processor, and may include dual microprocessor and multi-processor architectures. The communication interface 706 facilitates wired or wireless communication between the computing device 702 and other devices. The storage device 708 may be a computer-readable medium that does not contain a propagation signal, such as a modulated data signal transmitted by a carrier wave. Examples of the storage device 708 include, but are not limited to, RAM, ROM, EEPROM, flash memory or other storage technology, CD-ROM, digital versatile disk (DVD) or other optical storage device, magnetic cassette, magnetic tape, magnetic disk storage device, all of which do not contain a propagation signal, such as a modulated data signal transmitted by a carrier wave. There may be multiple storage devices 708 in the computing device 702. The input device 710 may include a keyboard, a mouse, a pen, a voice input device, a touch input device, etc., and any combination thereof. The output device 714 may include a display, a speaker, a printer, etc., and any combination thereof.
[0065] The memory 712 may be any non-transitory computer-readable storage medium that can store executable programs, applications, and data. The computer-readable storage medium does not involve propagating signals, such as modulated data signals transmitted by carrier waves. The computer-readable storage medium may be any type of non-transitory memory device (e.g., random access memory, read-only memory, etc.), magnetic storage device, volatile storage device, non-volatile storage device, optical storage device, DVD, CD, floppy disk drive, etc., which does not involve propagating signals, such as modulated data signals transmitted by carrier waves. The memory 712 may also include one or more external storage devices or remotely located storage devices, which do not involve propagating signals, such as modulated data signals transmitted by carrier waves.
[0066] The memory 712 may contain instructions, components, and data. A component is a software program that performs a specific function, which is also referred to as a module, program, and / or application. The memory 712 may include an operating system 716, one or more source code files 718, a compiler 720, executable code 722, including compiler-generated asynchronous enumerations 724 and asynchronous enumerable objects 726, and other applications and data 728.
[0067] Figure 8 Another operating environment 800 is shown that utilizes a cloud service 802 to perform a compilation service for a user associated with one or more client machines 804. The cloud service 802 interacts with one or more client machines 804 over a network 816 to compile one or more source code files 818 into executable code 820 including compiler-generated asynchronous enumerations and compiler-generated asynchronous enumerable classes. The cloud service may include one or more computing devices 806, each of which may include one or more processors 808, memory 810, and a network interface 812. The memory may include a compiler 814 that receives source code files 818 from client machines 804 and operates as described above to generate executable code 820. The client machine 804 may be any type of computing device that may include one or more processors 826, memory 828, and a network interface 830. The memory 828 of the client machine 804 may include the source code files 818 and the executable code 820 received from the cloud service 802.
[0068] A system is disclosed, the system having at least one processor coupled to a memory and a compiler. The compiler creates a class for executing asynchronous enumeration, the class including an asynchronous enumerable and operations required to execute enumeration of the asynchronous enumerable, the operations including suspending execution of iterations at a suspension point to wait for completion of the asynchronous operation, and resuming execution of the iterations at a resume point after completion of the asynchronous operation, and the compiler generates a first set of instructions and a second set of instructions, the first set of instructions allocating an asynchronous enumerable object based on the class at runtime for the asynchronous enumerable, and the second set of instructions enumerating the asynchronous enumerable using a single asynchronous enumerable object.
[0069] The class includes: methods to obtain an enumerator to traverse an asynchronous enumerable object; methods to cause the enumerator to move to the next state of the iteration upon completion of an asynchronous operation; an awaitable that provides notification when an asynchronous operation completes; methods to determine whether an asynchronous operation has completed processing, obtain results associated with the completion of the asynchronous operation, and resume processing at a recovery point upon completion of the asynchronous operation; a state machine that includes local data associated with the suspended iteration and executable instructions of the asynchronous enumerable; and methods that facilitate continuing to a recovery point upon completion of an asynchronous operation. The class includes implementations for one or more of the following: an asynchronous enumerator interface, an asynchronous enumerable interface, an awaitable interface, and an awaiter interface.
[0070] A device is disclosed, comprising at least one processor and a memory. The at least one processor is configured to: receive a program including an asynchronous enumerable and an asynchronous enumeration, the asynchronous enumerable including an asynchronous operation, the asynchronous enumeration consuming the asynchronous enumerable; create a class for the asynchronous enumerable, the class including an implementation of an asynchronous enumerator interface, an implementation of an asynchronous enumerable interface, an implementation of an awaitable interface, and an implementation of an awaiter interface; convert the asynchronous enumeration into a set of instructions, the set of instructions using the operations of the class to perform the asynchronous enumeration; and generate executable code, the executable code calling a single object based on the class for all iterations of the asynchronous enumerable. The implementation of the awaitable interface provides notification when the asynchronous operation is completed.
[0071] An implementation of the asynchronous enumerator interface provides methods for moving an asynchronous enumerable to the next element, an implementation of the asynchronous enumerable interface includes a protocol for enumerating an asynchronous enumerable and operations for obtaining an enumerator that traverses the enumerable, an implementation of the waiter interface includes operations for hooking up continuation at a recovery point, determining whether an asynchronous operation has completed, and obtaining results of an asynchronous operation, and an implementation of the waitable interface includes operations for indicating whether there are additional elements in the asynchronous enumerable.
[0072] A method that can be implemented on a system or device disclosed herein is disclosed, the method generating a reusable object for use in executing at least one iteration of an asynchronous enumerable, the asynchronous enumerable including an asynchronous operation, the reusable object including an enumerable, an enumerator, an awaitable, and an awaiter; executing at least one iteration of the asynchronous enumerable; and suspending processing of the current iteration until the awaiter signals completion of the asynchronous operation when it is determined through the awaitable that the asynchronous operation has not been completed.
[0073] The method also performs the following actions: after the waiter's notification signal notifies the completion of the asynchronous operation, resuming the state of the suspended iteration at a resumption point; synchronously determining that there is at least one element in the asynchronous enumerable that has not been processed and continuing to iterate with the at least one element; synchronously determining that there are no more elements in the asynchronous enumerable and completing the enumeration of the asynchronous enumerable; creating a class containing an implementation for iterating the asynchronous enumerable at compile time, wherein the reusable object is based on the class; and converting code that consumes the asynchronous enumerable into code that uses the implementation of the enumerable, enumerator, awaitable, and waiter in the reusable object to perform at least one iteration.
[0074] Although the subject matter has been described in language specific to structural features and / or methodological acts, it should be understood that the subject matter defined in the appended claims is not necessarily limited to the specific features or acts described above. Rather, the specific features and acts described above are disclosed as example forms of implementing the claims.< / int> < / t> < / t> < / t> < / t> < / t> < / t> < / t> < / t> < / t> < / int> < / int> < / t> < / t> < / t> < / t> < / t> < / t> < / t> < / t> < / t> < / t>
Claims
1. A compilation system, comprising: at least one processor coupled to the memory; as well as compiler, the compiler creating a class to perform an asynchronous enumeration, the class including an asynchronous enumerable and operations required to perform enumeration of the asynchronous enumerable, the operations including suspending execution of an iteration at a suspension point to await completion of an asynchronous operation and resuming execution of the iteration at a resume point upon completion of the asynchronous operation, and A first set of instructions and a second set of instructions are generated, the first set of instructions allocating an asynchronous enumerable object based on the class at runtime for the asynchronous enumerable, and the second set of instructions enumerating the asynchronous enumerable using a single asynchronous enumerable object.
2. The system of claim 1, wherein the class includes a method to obtain an enumerator to traverse the asynchronous enumerable.
3. The system of claim 2, wherein the class includes a method to move the enumerator to a next state of iteration upon completion of the asynchronous operation.
4. The system of claim 1, wherein the class includes an awaitable object that provides notification when the asynchronous operation completes.
5. The system of claim 1, wherein the class includes at least one method that determines whether the asynchronous operation has completed processing, obtains a result associated with the completion of the asynchronous operation, and resumes processing at a resume point after the completion of the asynchronous operation.
6. The system of claim 1, wherein the class comprises a state machine comprising local data associated with a pending iteration and executable instructions of the asynchronous enumerable.
7. The system of claim 1, wherein the class includes a method that facilitates continuing to a recovery point when the asynchronous operation completes.
8. The system of claim 1, wherein the class comprises implementations for one or more of: an asynchronous enumerator interface, an asynchronous enumerable interface, an awaitable interface, and a waiter interface.
9. A method implemented on a computing device having at least one processor and a memory, the method comprising: generating a reusable object for use in executing at least one iteration of an asynchronous enumerable, the asynchronous enumerable comprising an asynchronous operation, the reusable object comprising an enumerable, an enumerator, an awaitable, and an awaiter; executing said at least one iteration of said asynchronous enumerable; Upon determining, by the awaitable, that the asynchronous operation has not completed, processing of the current iteration is suspended until the awaitable signals completion of the asynchronous operation.
10. The method according to claim 9, further comprising: After the waiter's notification signals completion of the asynchronous operation, the state of the suspended iteration is resumed at a resume point.
11. The method according to claim 9, further comprising: Synchronously determining that there is at least one element in the asynchronous enumerable that has not yet been processed; as well as Continue iterating with the at least one element.
12. The method according to claim 9, further comprising: synchronously determining that there are no more elements in the asynchronous enumerable; as well as Completes enumeration of the asynchronous enumerable.
13. The method according to claim 9, further comprising: A class is created that contains an implementation for iterating over the asynchronous enumerable at compile time, wherein the reusable object is based on the class.
14. The method according to claim 9, further comprising: Converting code that consumes the asynchronous enumerable to code that uses the enumerable, the enumerator, the awaitable, and the implementation of the awaiter in the reusable object to perform the at least one iteration.
15. A compiling device, comprising: at least one processor and memory; wherein the at least one processor is configured to: receiving a program comprising an asynchronous enumerable and an asynchronous enumeration, the asynchronous enumerable comprising an asynchronous operation, the asynchronous enumeration consuming the asynchronous enumerable; Creating a class for the asynchronous enumerable, the class containing operations for performing the asynchronous enumerable, the class including an implementation of an asynchronous enumerator interface, an implementation of an asynchronous enumerable interface, an implementation of an awaitable interface, and an implementation of a waiter interface; converting the asynchronous enumeration into a set of instructions, the set of instructions executing the asynchronous enumeration using the operations of the class; as well as Executable code is generated that calls a single object based on the class for all iterations of the asynchronous enumerable.
16. The apparatus of claim 15, wherein the implementation of the waitable interface provides notification when the asynchronous operation completes.
17. The apparatus of claim 15, the implementation of the asynchronous enumerator interface providing a method to move the asynchronous enumerable to a next element.
18. The apparatus of claim 15, wherein the implementation of an asynchronous enumerable interface includes a protocol to enumerate the asynchronous enumerable and operations to obtain an enumerator that traverses the enumerable.
19. The apparatus of claim 15, wherein the implementation of the waiter interface includes operations for hooking a continuation at a resume point, determining whether the asynchronous operation has completed, and obtaining a result of the asynchronous operation.
20. The apparatus of claim 15, wherein the implementation of the awaitable interface includes an operation to indicate whether there are additional elements in the asynchronous enumerable.
Citation Information
Patent Citations
Resumable methods
CN102859489A
Interaction with nested and non-nested streams
US20050183071A1