A really good library that we use is libco[0], it supports different architectures and mechanisms. We use it extensively on Fluent Bit[1] to manage async IO network operations (epoll + coroutines).
A cool library that implements C coroutines, available for both idiomatic C (http://libdill.org/) and in the same style as Go (http://libmill.org/) with line by line translations
libdill and co implement stackful coroutines. Each coroutine has a native call stack which gets swapped out by a userspace scheduler. Rusts proposed coroutines and async functions are stackless. They are implemented as pure Compiler Transformations, and don’t allow to yield at arbitrary points.
Rust actually had stackless coroutines in the past (libgreen), but moved from it due to the overhead it brought for code that didn’t require it.
I ran with this idea last year and wrote a proof of concept library that wraps libev using using this concept to allow you to write async C code inline. It's about 250 lines of macro abuse and the resulting code looks pretty funky but it ultimately works. I have a simple echo server example here: https://github.com/jeremycw/zasync/blob/master/echo_server.c
As an OOP dev this kind of horrifies me, even though it works okay (though it's surely not thread-safe?)
Nevertheless, even in C, I'd find it conceptually simpler to understand if the functions were written as pure functions, returning a tuple with (c, state) and passing the state back into the caller. Using non-idiomatic tricks and macros in this way is harder to read and understand.
Here's a POSIX compliant portable getopt() routine I wrote which uses this style. Is this hard to read? Note that it's several times shorter than every other implementation I've ever seen, and if I do say so myself I think it's eminently readable.
Has anyone used these to write interrupt service routines? Seems like there's an opportunity here. You can take your existing synchronous code and not have to rewrite it into something like continuation-passing style. This is a source of a lot of bugs.
i have done cps plumbing in C with poor mans closures for the entire interrupt path, and given its natural event-like nature, it really all comes out pretty nice.
the actual work was done under contract as in proprietary, but the closure library is the interesting part, is owned by me, and something i can send you.
accountname @gmail.com
if you're interested we can go over the interrupt path, its pretty straightforward at that point. by flipping the control flow around, the virtio virtqueue support for example becomes nice and self-contained. it provides an interrupt continuation to the interrupt layer, and each queue is initialized with a continuation to call on a dequeue. vector assignment is still a bit cross-cutting.
> Protothreads is a library implementation of this trick. In fact, the protothreads creator even references the linked site in their explanation of protothreads (very last paragraph)
c should not be a char or unsigned char, because the return type of getchar() is "int". If you put it into a char-width variable then you lose the distinction between EOF (which is -1) and the byte 0xff. Getting the type of 'c' wrong is quite a common bug, because the API makes it an easy mistake to make. In this case, if you look down at the eventual transformed code in the "Evaluation" section you'll see that 'c' is indeed correctly declared with 'int' type.
I guess one of the applications of Coroutines could be WebAssembly. When you run WebAssembly on a website which needs 100% of the CPU for more than a few ms, you have to use the "setTimeout(fn, 0)" trick to prevent the "this website stopped responding" message. That means you have to store the current state at some point and continue in the function fn (after waiting 0 ms). Languages which support coroutines out of the box would help a lot here.
The web worker helps a little bit. You can send data to the UI thread whenever you want. However on the receiving side you have the same problem. The web worker only receives data when it is idle. For example if you want to send key presses to the web worker, the web worker has to idle. The utilization of the CPU to 100% with simultaneous responsiveness is quite difficult to implement. Actually you have to play an endless game of message ping pong so that the message queue is always filled.
Protothreads is a library implementation of this trick. In fact, the protothreads creator even references the linked site in their explanation of protothreads (very last paragraph) [1].
That page uses very simple HTML. Just paragraphs of text divided into sections with headings. Some code examples laid out side-by-side with a table. Tiny stylesheet. No JS. Loads quickly, easy to read. Warms the cockles of my heart.
Back in the day, we had multiple windows on the screen at one time, so this wasn't a problem. I think it was Windows which defaulted to full-screen, and led to the plague of sites assuming that the browser would be full-width on a landscape screen, but I could be wrong.
Although I love using a tiling window manager now, I kinda miss my old System 8 Macintosh setup, with Netscape open in one window & Think C (or was it CodeWarrior?) open in another.
I like landscape — I can comfortably fit 3 80-column code tabs with linter columns (vim :vsplit) in landscape mode, or a vertical term (with 2 80-col code tabs, uncomfortably) and browser side by side.
And it also works when I want to play games, or watch anything recorded in landscape, which is most media.
This page is written by the creator of PuTTY. They could probably release this as a straight TXT file and still get the readership they deserve. Simon Tatham know's what he's doing!
It really shouldn't be the web designer's job to pick a width that the content will display as and impose that unilaterally on everyone.
That way it's easy for everyone to make their own choices. If you want 27" wide lines of text, go ahead and full-screen that browser and have at it. If you want the text you're reading to take up less horizontal real estate than that, then you can easily make the browser itself as wide or narrow as you like.
Because it's not ergonomic. You don't need the browser to take up your entire screen, you just need it big enough so you can fit the content comfortably.
Admittedly we would all lose this habit quicker if resizing windows wasn't such a finicky process in most OSs
sadly abandoned it seems, and not well-known, but is well-working in both win7 and win10. With a keyboard shortcut it's easy to resize any window and at the same time position them on the screen.
Also makes it easy to "save" windows that have slightly bad size or position so it's hard to position the mouse pointer in the resize corner.
On my wish list is that after bringing up the application, instead of using the mouse to select grid, I should be able to use eg arrow keys and shift to select them.
If you're viewing documents, they're typically more vertically than horizontally oriented. That is, the parts you need to see more of are above/below of the viewable portion, not left/right of the viewable portion. So a browser being used for reading is often more useful when it takes up maybe half the screen on a high-res/large monitor.
If you're accessing webapps, that have more objects arranged horizontally, then going fullscreen may be more useful (think Trello boards and other things).
- [0] https://byuu.org/library/libco/
- [1] https://fluentbit.io