1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Threading;
  8 
  9 namespace System.Threading.Fibers
 10 {
 11     public delegate void FiberFunction(void* param);
 12 
 13     internal class FiberData
 14     {
 15         public nothrow FiberData(const FiberFunction& function_void* param_) : function(function_)param(param_)
 16         {
 17         }
 18         public inline nothrow FiberFunction Function() const
 19         {
 20             return function;
 21         }
 22         public inline nothrow void* Param() const
 23         {
 24             return param;
 25         }
 26         private FiberFunction function;
 27         private void* param;
 28     }
 29 
 30     public class Fiber
 31     {
 32         public nothrow Fiber() : handle(null)main(true)
 33         {
 34             handle = RtConvertThreadToFiber(null);
 35         }
 36         public nothrow Fiber(const FiberFunction& function) : this(cast<ulong>(1024u) * 1024ufunctionnull)
 37         {
 38         }
 39         public nothrow Fiber(const FiberFunction& functionvoid* param) : this(cast<ulong>(1024u) * 1024ufunctionparam)
 40         {
 41         }
 42         public nothrow Fiber(ulong stackSizeconst FiberFunction& function) : this(stackSizefunctionnull)
 43         {
 44         }
 45         public nothrow Fiber(ulong stackSizeconst FiberFunction& functionvoid* param) : handle(null)main(false)
 46         {
 47             FiberRunFunction runFiber = RunFiber;
 48             void* startAddress = cast<void*>(runFiber);
 49             handle = RtCreateFiber(stackSizestartAddressnew FiberData(functionparam));
 50         }
 51         public void SwitchTo()
 52         {
 53             if (handle != null)
 54             {
 55                 RtSwitchToFiber(handle);
 56             }
 57             else
 58             {
 59                 throw ThreadingException("could not switch to this fiber: handle is null");
 60             }
 61         }
 62         public suppress nothrow Fiber(const Fiber&);
 63         public suppress nothrow void operator=(const Fiber&);
 64         public nothrow Fiber(Fiber&& that) : handle(that.handle)main(that.main)
 65         {
 66             that.handle = null;
 67             that.main = false;
 68         }
 69         public default nothrow void operator=(Fiber&& that);
 70         public ~Fiber()
 71         {
 72             if (handle != null)
 73             {
 74                 if (!main)
 75                 {
 76                     RtDeleteFiber(handle);
 77                 }
 78             }
 79         }
 80         public inline nothrow void* Handle() const
 81         {
 82             return handle;
 83         }
 84         public static nothrow Fiber FromCurrentThread()
 85         {
 86             return Fiber();
 87         }
 88         private void* handle;
 89         private bool main;
 90     }
 91 
 92     public void SwitchToFiber(const Fiber& fiber)
 93     {
 94         fiber.SwitchTo();
 95     }
 96 
 97     internal delegate void FiberRunFunction();
 98 
 99     internal void RunFiber()
100     {
101         void* data = RtGetFiberData();
102         UniquePtr<FiberData> fiberData(cast<FiberData*>(data));
103         FiberFunction function = fiberData->Function();
104         void* param = fiberData->Param();
105         function(param);
106     }
107 }