Listen

Description

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.

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.