Live data from Hacker News

Fiber in C++: Understanding the Basics

agraphicsguynotes.com

61–70 of 77 posts

Re: Fiber in C++: Understanding the Basics

#61

    Some readers may have a question by now. What is the rationale behind the choices of the registers that need to be stored?
Yet another article that goes into the gorey details of how fiber works but not how fibers are used.

How do we write the "Applications own scheduler"?

Re: Fiber in C++: Understanding the Basics

#62

I'm confused in how this article defines "fiber." At the beginning of the article, fibers are described as a lightweight userspace thread, similar to what is provided in the runtimes of Haskell and Go, and has been recently revived in Java as "virtual threads." However, later in the article (after a long and apparently irrelevant digression about stack management), they describe Windows API functions that are require…

Setting aside certain implementation details, here's the basics: Kernel Threads (aka threads): OS-Level and preemptive. Green Threads (aka lightweight threads, virtual threads or goroutines): User-level and preemptive. Fibers: User-level (sometimes OS-level or offered as a OS library, like in Windows) and cooperative. Coroutines: User-level and cooperative.

There's one thing missing here, whereas fibers are cooperative, they have a user space scheduler deciding which fiber to switch to on a thread when you yield, coroutines specify who they're yielding to.

Re: Fiber in C++: Understanding the Basics

#63

I believe that fibers are considered more trouble than they worth? [0] [0] https://devblogs.microsoft.com/oldnewthing/20191011-00/?p=10...

The Gor Nishanov paper linked in that piece goes into a lot of detail of some of the downsides of fibers in an unmanaged language like C++.

[0] http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p136...

Re: Fiber in C++: Understanding the Basics

#65
Some random historical notes coroutine stuff which are perhaps of interest to some:

1. You can implement "stack-free coroutines" in C with some really entertaining macros https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

2. Does anyone remembers Cilk? Its still the fastest stackful coroutine models I know of.

Having implemented and used both before (for different purposes), I like both, but with a mild preference for the stackful version. Largely because you don't have function coloring problems, and you can actually get a proper stack trace and is so significantly easier to debug when things go wrong.

It is also good to differentiate coroutines from async (they seem to be very interleaved these days). Coroutines are a mechanic to achieve mutual recursion / generators. And that is fine for expressing certain algorithms and systems in a much cleaner fashion. Note that parallelism is not necessarily implied by "coroutine".

Async is a mechanic to "doing something else" while waiting for IO. Fibers or state machines are both different solutions to this problem. Certain coroutine implementations can help with this, but I think it is massively overused. Rust due to the function coloring problem, ends up requiring almost everything to be marked "async". And some golang code I have read seems to overuse goroutines unecessarily. I think use of async should be narrow and minimized, and localized to only the places where it makes sense.

Re: Fiber in C++: Understanding the Basics

#66

Earlier quoted context omitted.

It is an OS component, it's provided in kernel32.dll and accesses internal OS data structures that are not publicly defined or stable between versions. You cannot safely implement fibers in Windows without the fibers API, period. Boost.Context's direct Windows context switching code hacks undocumented fields in the TIB: https://github.com/boostorg/context/blob/6fa6d5c50d120e69b2d... ...and this causes problems, becau…

That bug was caused by the TLS slots pointer being uninitialized in the newly created Boost fiber, not a change in Windows API. TLS pre-dates boost::context, the field had existed since the very first commit. I already said "MS would rather you not", obviously, otherwise they would have documented the TIB. The fact remains that tons of production systems rely on officially-unofficial elements of NT's architecture and…

The bug was caused by Boost.Context manipulating OS data structure fields that it has no business changing.

And yes, those fields do now have to be maintained for backwards compatibility -- because libraries like Boost.Context hardcoded this into applications, unbeknownst to the users of that library.

Re: Fiber in C++: Understanding the Basics

#67
post #62

Earlier quoted context omitted.

Setting aside certain implementation details, here's the basics: Kernel Threads (aka threads): OS-Level and preemptive. Green Threads (aka lightweight threads, virtual threads or goroutines): User-level and preemptive. Fibers: User-level (sometimes OS-level or offered as a OS library, like in Windows) and cooperative. Coroutines: User-level and cooperative.

There's one thing missing here, whereas fibers are cooperative, they have a user space scheduler deciding which fiber to switch to on a thread when you yield, coroutines specify who they're yielding to.

As per article, Windows fibers literally have a SwitchToFiber call and come with no scheduler. So there is really ni difference.

Re: Fiber in C++: Understanding the Basics

#68
post #65

Some random historical notes coroutine stuff which are perhaps of interest to some: 1. You can implement "stack-free coroutines" in C with some really entertaining macros https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html 2. Does anyone remembers Cilk? Its still the fastest stackful coroutine models I know of. Having implemented and used both before (for different purposes), I like both, but with a mild pre…

> Does anyone remembers Cilk?

Yes! It's a shame it never gained traction and Intel abandoned it, eventually getting dropped from icc and gcc.

Re: Fiber in C++: Understanding the Basics

#69

Earlier quoted context omitted.

Fun fact, what you call async is also widely referred to as coroutines. Stackless coroutines vs stackful coroutines seems like the most appropriate way to disambiguate the two.

Thanks, stackful/stackless is noted for next time. I still kinda like using "async" as a shorthand for stackless coroutines though.

Before async for I/O became popular, stackless coroutines were mainly used for generator abstractions (for example yield in python), so async can be reductive.

Re: Fiber in C++: Understanding the Basics

#70
post #62

Earlier quoted context omitted.

There's one thing missing here, whereas fibers are cooperative, they have a user space scheduler deciding which fiber to switch to on a thread when you yield, coroutines specify who they're yielding to.

As per article, Windows fibers literally have a SwitchToFiber call and come with no scheduler. So there is really ni difference.

You'll notice the function's documentation is "Schedules a fiber. The function must be called on a fiber." so while it may not be a literal difference (after all they're both semi-user space), they are difference systems to use, but they're both roughly at the same level of "power".

If you're not using a scheduler with fibers then I'd argue you shouldn't be calling it a fibers system (and rather coroutines), since otherwise it's a distinction without a difference.

Post reply on HN