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 }