1 using System;
  2 using System.Threading.Fibers;
  3 
  4 public class Context
  5 {
  6     public Context() : mainFiber(null)otherFiber(null)runningFiber(null)otherFiberRunning(false)
  7     {
  8     }
  9     public void SetFibers(Fiber* mainFiber_Fiber* otherFiber_)
 10     {
 11         mainFiber = mainFiber_;
 12         otherFiber = otherFiber_;
 13         runningFiber = mainFiber;
 14     }
 15     public void SetOtherFiberRunning(bool running)
 16     {
 17         otherFiberRunning = running;
 18     }
 19     public bool IsOtherFiberRunning() const
 20     {
 21         return otherFiberRunning;
 22     }
 23     [nodiscard]
 24     public Result<bool> Switch()
 25     {
 26         if (runningFiber == mainFiber)
 27         {
 28             runningFiber = otherFiber;
 29             auto result = SwitchToFiber(*otherFiber);
 30             if (result.Error()) return result;
 31         }
 32         else
 33         {
 34             runningFiber = mainFiber;
 35             auto result = SwitchToFiber(*mainFiber);
 36             if (result.Error()) return result;
 37         }
 38         return Result<bool>(true);
 39     }
 40     private Fiber* mainFiber;
 41     private Fiber* otherFiber;
 42     private Fiber* runningFiber;
 43     private bool otherFiberRunning;
 44 }
 45 
 46 public void FiberHelper(Context* context)
 47 {
 48     Console.Out() << "in fiber helper" << endl();
 49     int count = 1;
 50     while (count <= 3)
 51     {
 52         Console.Out() << "switching context from fiber helper, count = " << count << endl();
 53         auto result = context->Switch();
 54         if (result.Error())
 55         {
 56             Console.Error() << result.GetErrorMessage() << endl();
 57             return;
 58         }
 59         Console.Out() << "back in fiber helper, count = " << count << endl();
 60         ++count;
 61     }
 62     Console.Out() << "exiting fiber helper" << endl();
 63 }
 64 
 65 public void FiberFunc(void* data)
 66 {
 67     Console.Out() << "in fiber" << endl();
 68     Context* context = cast<Context*>(data);
 69     context->SetOtherFiberRunning(true);
 70     auto result = context->Switch();
 71     if (result.Error())
 72     {
 73         Console.Error() << result.GetErrorMessage() << endl();
 74         return;
 75     }
 76     FiberHelper(context);
 77     context->SetOtherFiberRunning(false);
 78     Console.Out() << "fiber exiting" << endl();
 79     result = context->Switch();
 80 }
 81 
 82 public int main()
 83 {
 84     Context context;
 85     Fiber mainFiber = Fiber.FromCurrentThread();
 86     FiberFunction fiberFunction = FiberFunc;
 87     Fiber otherFiber(fiberFunction&context);
 88     context.SetFibers(&mainFiber&otherFiber);
 89     auto result = context.Switch();
 90     if (result.Error())
 91     {
 92         Console.Error() << result.GetErrorMessage() << endl();
 93         return 1;
 94     }
 95     Console.Out() << "back in main fiber" << endl();
 96     while (context.IsOtherFiberRunning())
 97     {
 98         Console.Out() << "switch context from main fiber" << endl();
 99         result = context.Switch();
100         if (result.Error())
101         {
102             Console.Error() << result.GetErrorMessage() << endl();
103             return 1;
104         }
105         Console.Out() << "back in main fiber" << endl();
106     }
107     Console.Out() << "exiting main" << endl();
108     return 0;
109 }