Live data from Hacker News

Implementing simple cooperative threads in C

brennan.io

41–50 of 88 posts

Re: Implementing simple cooperative threads in C

#41

we used something similar when I was writing games in the early to mid 90's, but our yield function was simply called yield(). we were running on windows (3.11), macOS, and amiga (for tooling, the games didn't run on the amiga) with great success. of course, we just used setjmp and longjmp, no assembly for portability (though there ended up being some assembly in one of the games, while macOS had good sound managemen…

DIV Games Studio, a language and IDE to develop DOS games on late 90's, used coroutines on a similar fashion. Even it had priority levels, signals and hierarchies of coroutines. On DIV parlance, this coroutines where called "process", and yield() was called "frame()". I managed to remake this from scratch, using D fibers, for a pet/toy game engine that I'm writing.

Re: Implementing simple cooperative threads in C

#43
post #4

Earlier quoted context omitted.

Does your blood pressure also rise from use of exceptions? Because the pattern that emerges with setjmp/longjmp is pretty similar, and that's the most common use: to simulate what other languages offer with exceptions. The most prominent libraries I can think of that force you to do this are image related, libpng and libjpeg both use longjmp to handle errors [though IIRC it's optional in the latter].

Are there exceptions in C? If I’m interviewing someone for a programming job and I see goto in there C code... they better have an amazing reason or they won’t be getting the job. Harsh, but it’s reality of how few people are suited for embedded programming.

Standard C has no exceptions.

Goto is the typical way to handle errors without creating a hell mess of "hm, gotta close this file, free that buffer, blah blah" at every step where you might want to bail early. There are a few alternatives but none of them are better than goto and a few can be said to be worse.

Re: Implementing simple cooperative threads in C

#44
I wonder how hard it would be to try handle the segfault and allocate stack space on demand for these “threads”. Almost certainly stupid but a fun experiment to see if its possible...

EDIT: found a nice example of this here: https://rethinkdb.com/blog/handling-stack-overflow-on-custom...

Re: Implementing simple cooperative threads in C

#45

we used something similar when I was writing games in the early to mid 90's, but our yield function was simply called yield(). we were running on windows (3.11), macOS, and amiga (for tooling, the games didn't run on the amiga) with great success. of course, we just used setjmp and longjmp, no assembly for portability (though there ended up being some assembly in one of the games, while macOS had good sound managemen…

DIV Games Studio, a language and IDE to develop DOS games on late 90's, used coroutines on a similar fashion. Even it had priority levels, signals and hierarchies of coroutines. On DIV parlance, this coroutines where called "process", and yield() was called "frame()". I managed to remake this from scratch, using D fibers, for a pet/toy game engine that I'm writing.

I've always really liked the idea of cooperative multitasking: fewer gotchas, possibly safer memory access, and easier to control where/when a thread switches. of course in those days we had to deal with timing issues, couldn't let a cpu hog block another cpu hog :)

Re: Implementing simple cooperative threads in C

#46
post #31

Another interesting approach to lightweight cooperative threading is Protothreads [1][2]. Those are however stackless and make use of duff's device for the implementation; rather, than setjmp/longjmp. [1] http://dunkels.com/adam/pt/ [2] https://en.wikipedia.org/wiki/Protothread

On GCC/Clang, pt uses goto and the “labels as values” GNU extension so it can avoid Duff’s device. This simplifies things, and allows yielding inside a switch statement.

Re: Implementing simple cooperative threads in C

#47
post #4

Earlier quoted context omitted.

Does your blood pressure also rise from use of exceptions? Because the pattern that emerges with setjmp/longjmp is pretty similar, and that's the most common use: to simulate what other languages offer with exceptions. The most prominent libraries I can think of that force you to do this are image related, libpng and libjpeg both use longjmp to handle errors [though IIRC it's optional in the latter].

Are there exceptions in C? If I’m interviewing someone for a programming job and I see goto in there C code... they better have an amazing reason or they won’t be getting the job. Harsh, but it’s reality of how few people are suited for embedded programming.

While not being a prescribed way of doing things (deservedly) goto as well as some other "obsolete" tricks sometimes can actually make sense in low level C code especially on micro-controllers.

Denying potential job to a person on a basis of generic "goto is anathema" mantra is not a good idea until one looks at the code and understands what the "offensive" part is actually doing instead of using some code analyzer/text search blindly.

Re: Implementing simple cooperative threads in C

#49
post #9

FWIW, the original implementation of Java (when it was known as Oak) used this trick to manage user level threading. There was also a some code to do the stack swap since you were in a virtual machine anyway, that stuff was all there to be adjusted. Random meta note brenns10, the idiom for giving up the processor is 'yield' (rather than 'relinquish') it is common in cooperative systems. That said, the code in Java th…

the idiom for giving up the processor is 'yield'

Back in the old 8-bit days we called it “sleep” since you were telling the scheduler if you needed to come back ASAP (i.e. sleep(0)) or N number of microseconds in the future.

Re: Implementing simple cooperative threads in C

#50

The main problems I've seen with cooperative threading (aka fibers) are threefold: 1. You need to decide how much stack space to allocate to a fiber beforehand. If you go over this limit, you will segfault. 2. Thread local storage doesnt exist anymore since you're potentially swapping between different kernel threads (and different fibers are using the same thread and will share storage). 3. Certain types of locks ca…

(2) and (3) are sort of symptoms of trying to use the C runtime in what is definitely not a native C threading environment.

(1), Golang does something like this by probing on every function call and having movable stacks. Historically they used a linked list of stack pages, but gave that up in 1.4 because the performance was bad. The same does not work in C because C compilers do not expect pointers to the stack to become invalid while a stack frame is live.

Post reply on HN