Version 3 of NRE: Coroutines in 8.6

Updated 2008-10-22 23:48:26 by LV

The second talk in Miguel Sofer's NRE series at Tcl2008, following up on NRE: the non-recursive engine in Tcl 8.6:

Coroutines--what?

  • A computation that can be suspended and resumed on demand or killed while suspended
  • A tool to create generators
  • A tool to simplify the coding of event-based programs
  • A tool to enable cooperative multitasking within a single interp, without OS support

TIP #328 [L1 ] specifies three new commands: coroutine, yield, and info coroutine. [coroutine] is evaluated equivalently to uplevel #0 [list cmd ?arg ...?]. [yield] suspends operation. Walked through an example from the tip.

[yield] returns twice: when yielding (caller reeives a return value from the yielding coroutine); when resuming coroutine sees the [yield] command returning. [cmdName] is "garbage collected". Example at http://msofer.com:8080/wiki?name=Coroutines

Went through the wiki page Coroutines for event-based programming showing converting a console application to a GUI.

Coroutines: why?

  • GUI programming "made easier" (NEM)
  • nestable vwaits?
  • Generators
  • Servers (wub)
  • Cooperative multitasking (event loop)
  • Cooperative multitasking (dispatcher)

Wil need to learn from experience which is better/faster (event loop vs dispatcher)

Coroutines: tech?

  • [coroutine]: creats a command and a new execEnv for it; callback in the old execEnv to swap back to it; swaps in the new execEnv, callback to clean up; launches script
  • [yield]: freezes TEBC; swaps out coro's execEnv; returns value

The byte code engine doesn't know much about coroutines; things happen behind its back (that's mostly true).

Deleting a suspended coroutine winds-down the suspended execution (as if interp's limit had been reached).

Special considerations:

  • Commands run at [uplevel #0]
  • You can yield from a nested call. These are asymmetric stackful coroutines in terms of Lua
  • If the command pushes a CallFrame (proc or lambda): local variables retain their state when suspended, local variables are at level #1

Tailcalls: what?

(...Due to time constraints a couple slides were on screen for only a few seconds each...)

A pseudo-implementation (may be useful for debugging purposes: stack trace!):

 proc tailcall args {
     set cmd [[uplevel 1 [[\
         list namespace which [[lindex $args 0]]]]]]
     lset args 0 $cmd
     uplevel 2 $args
 }

Tailcalls: why?

  • Infinite recursion depth possible
  • Functional programming constructs
  • Psuedo-macros (without the speed gain)
  • continuation passing style
  • State machines
  • "Delegation"

Tailcalls: tech: [tailcall] arranges for the command to be run right after all callbacks that were scheduled by the callee's implementation.

Question from DKF: What's next Miguel? Answer: coffee?

Question from DGP about whether coroutine resume command name could be pre-resolved with [namespace origin]. Answer: great feature request.

Question from the chat about heap memory usage. (Some KB; didn't catch how many if coroutines used at all today; will be less before 8.6.0 is released).