29
12/11
Fibers in .NET – An Adventure in C++/CLI
C++ is the one area of programming that I’ve lamentably felt lacking, especially the more and more I get involved in programming specifically for Windows. Whereas Linux/POSIX programming feels designed unequivocally for C, Windows seems to gravitate more towards C++.
So, I took the opportunity—four days off—over the Christmas holidays to learn C++ and C++/CLI.
I also took the opportunity to do something that I’ve been wanting to do for a while—make a fiber library for .NET.
I’m not going to say that it’s complete (still some stuff I want to add to it), but here goes:
Source and XML file (containing documentation) within. If you want to compile it use cl.exe with the /clr flag on fiber_all.cpp (which #includes all the other cpp files and the header). Remember to specify /link /DLL /out:fiber.dll if you’re just compiling the source into a DLL to use with C# or something.
Example command line invocation:
cl.exe /Ox /clr fiber_all.cpp /link /DLL /out:fiber.dll
The /Ox is thrown in to enable optimization.
As an aside: If you’re trying to compile C# code against this with csc.exe, unless you used the 64-bit cl.exe, you’re going to have to go ahead and specify /platform:x86, otherwise your C# app will throw terrible exceptions and die as soon as it starts.
How it works:
All the classes that the library uses I took the liberty of putting in the namespace System.Threading, just for intuitiveness.
.NET threads are silly in their implementation—they don’t map onto native OS threads, and may be implemented as native threads, fibers, some combination of the two, or something else entirely, which means that if you just start up a .NET application, or create a new thread in one, a call to ConvertThreadToFiber may be illegal or dangerous—all-in-all, something you don’t want to do.
The library implements a property—Fiber.IsFiber—which can let you know whenever your code is running within an existing fiber. If you’re not in an existing fiber, and you create a new fiber, the library creates a new, native thread using CreateThread which it then converts to a fiber and immediately calls the function you provided to the fiber constructor.
Once you’re within a fiber, calling the constructor—without providing the new_thread—will create new fibers not attached to any thread, which can then be safely scheduled using SwitchTo.
The most interesting part is waiting for a group of fibers to finish. If the currently-running fiber “falls through” (i.e. ends and doesn’t call SwitchTo then the underlying thread ends. Since fibers can switch between threads, only the currently running fiber has a thread associated with it. By finding this fiber (the fiber with its Scheduled property set to true, you can get a FiberThreadWaitHandle from the WaitHandle property which will allow you to wait (just a wrapped call to WaitForSingleObject) for the underlying thread to terminate (calls to unscheduled threads will just return null).
Note that the Scheduled property is a bad way of finding the fiber to get the wait handle from, since the fiber could unschedule itself and schedule a different fiber in the time between when you call Scheduled and when you call WaitHandle, leading to a previously-scheduled fiber spitting null back at you. You should implement your own synchronization (I like to use a ManualResetEvent at the top of my initial fiber function, which waits ’till the main thread releases it after grabbing the wait handle).
When a fiber “falls through” its Finished property will become true, which means that you shouldn’t switch to it anymore, and should call Dispose on it to make sure the unmanaged underlying data types and operating system handles get cleaned up.
Comments, concerns, questions, just e-mail me.





).