I suggest you ...

Create a StackSaver class to facilitate State Management

Today the C# compiler is capable of creating a State Machine for us when a method returns IEnumerator or IEnumerable.
But, the state machine itself can be useful for void methods, but that's not all. Methods written that way must have a specific return type. I think it can be better if a class is created that "saves the stack values" and returns to the caller when the "YieldReturn" method is called (it can have a void version and a generic version for the return type).

Its usage could be like:
var stackSaver = new StackSaver(someDelegate);
At any point I can call:
stackSaver.MoveNext();

It will run the method pointed by someDelegate normally, but when that method calls:
StackSaver.StatcYieldReturn or stackSaver.YieldReturn(void or with some value) it saves the stack values (as they are already managed) and returns to the stackSaver.MoveNext next line.

When calling it again, it restores the stack and continues. This will allow for better state management, as the YieldReturn itself could be passed as a delegate, and so the same code may be "yield returning" if the delegate is the YieldReturn one or may be simple waiting some time if it is pointing to a Thread.Sleep.

Surely this will help games (Update method in special) a lot, but will be useful for enumerators and will be more versatile than the actual yield return, and will be available to any .Net compiler without compiler modification.

97 votes
Vote
Sign in
Check!
(thinking…)
Reset
or sign in with
  • facebook
  • google
    Password icon
    I agree to the terms of service
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Paulo ZemekPaulo Zemek shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    8 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      Submitting...
      • Paulo ZemekPaulo Zemek commented  ·   ·  Flag as inappropriate

        I also published an article on how the same resource (the StackSaver, Coroutine or ManagedFibers) could be used to do the same job of the async/await pair, but without requiring specific return types (which also makes general-purpose interfaces more prepared for future changes, as you don't risk breaking your code if some implementation needs to be "awaitable").

        The article is at: http://www.codeproject.com/Articles/357724/Async-Await-Could-Be-Better

      • dotnetchrisdotnetchris commented  ·   ·  Flag as inappropriate

        First triple vote I used. Adding this into .NET5 or .NET6 would make Node.js a TOTAL JOKE compared to .NET

      • Paulo ZemekPaulo Zemek commented  ·   ·  Flag as inappropriate

        After many research, I finally understood the right names.
        So, the StackSaver class that I am commenting may very well be named Coroutine. I already implemented a StackSaver class using full-threads, but I am sure it will be better avoiding new real-threads. Also, I did find that Fibers already allow such "stack-saving" and the creation of coroutines in the normal windows API, unfortunatelly it does not work in .Net even with p/invokes (ok, it works for some time... but then it crashes... I am sure it is related to garbage collection as the .Net does not see the alternative and unmanaged callstacks).
        So, I should put it here: Add managed Fibers to .Net.

      • Paulo ZemekPaulo Zemek commented  ·   ·  Flag as inappropriate

        In fact, my implementation on the matter (my POLAR compiler/interpreter) only updates a reference (a pointer). So, you are right, it will not copy the stack, it can only update a single pointer and make everything work.

      • QwertieQwertie commented  ·   ·  Flag as inappropriate

        I am voting for this with the assumption that it can be done with high performance, e.g. by not actually copying the stack but by changing the stack pointer.

        I suppose the stack size may have to be a multiple of the processor page size in order to work this way; so perhaps the user could request that when the stack is small (for a user-defined threshold, such as under 1KB) the saved stack should be copied to the main stack for execution, so that a full page of storage is not required. That would be most useful when stacks are long-lived and numerous, such as those that represent actors in a game. For temporary stacks such as one that represents an enumerator, it makes more sense to allocate a full 4K page (with an uncommitted 4K guard page afterward) even if the stack only uses 100 bytes, since only a few enumerators will be allocated at any given time.

      • Paulo ZemekPaulo Zemek commented  ·   ·  Flag as inappropriate

        I am actually creating a new compiler/interpreter and I am using it to prove the concept. You can see it working here: http://www.paulozemek.com/Polarlight.TestPage.aspx
        It uses the "stacksaver" for a method, and than yield returns at any moment, be it under finally blocks, be it from inner methods. In either case, it does not have any special return type.

      • DeonHe - MSFTDeonHe - MSFT commented  ·   ·  Flag as inappropriate

        Thank you all for voting on this idea. I have moved it to the team that can better address this issue.

        -Deon (MSFT)

      Feedback and Knowledge Base