Feb 13, 2019
Finally, the "we" in announcements doesn't just mean the royal we / majestic plural, but there's an actual co-host! Introduction is in the audio contents, so I guess you'll just have to listen. </clickbait>
We talk about first contact with the Rust programming language, coroutines for implementing lightweight tasks/threads, various smaller topics and some upcoming events.
Links:
Here's a code snippet hopefully illustrating what I called "coroutines" and should probably have been called "protothreads".
Function "print_2nd_word" is a protothread. It can be called repeatedly passing a character each time. Only the 2nd word is printed, one character at a time.
void print_2nd_word( char c )
{
CR_BEGIN;
while ( c != ' ' )
CR_YIELD;
CR_YIELD; // skip space
while ( c != ' ' ) {
putchar( c );
CR_YIELD;
}
}
To do this, the function keeps track of where it exited last time it was called, using a number of macros:
#define CR_BEGIN static void *jmp = &&lbl_crstart; goto *jmp; lbl_crstart: ( void )jmp;
#define CR_YIELD do { jmp = &&GLUE( lbl, __LINE__ ); return; GLUE( lbl, __LINE__ ): ( void )jmp; } while ( 0 )
"CR_BEGIN" is basically setup-code.
"CR_YIELD" is the simplest primitive in this context, and does: exit the protothread function, and resume at this point next time it's called.
More advanced macros - e.g. to repeatedly wait for an event - can be built on top of, or in the same way as "CR_YIELD".
Note that these macros use GCC's "computed gotos" (i.e. take the address of a C label, and jump to that address using "goto"). Here's an implementation of both macros using ANSI C:
#define CR_BEGIN static int cr_st = 0; switch( cr_st ) { case 0: ;
#define CR_YIELD do { cr_st = __LINE__; return; case __LINE__: ; } while( 0 )
#define CR_END CR_YIELD; }
(In this case, an additional macro "CR_END" is necessary as glue to conform to C syntax/nesting.)
Funfact: it's a bit of a PITA to add sourcecode to this page.