I considered using a C++ class, instances of which provide a coroutine connection. I had forgotten how much I dislike C++. C itself lacks closure logic and since Apple has discontinued support of gcc I fall back on the ‘C way of doing things’ and add an opaque argument to the PutGet function which locates where the stack-top of the partner lives. I consider this ugly on esthetic grounds. It is, however, a small modification to the one connection version.
The header file
The new PutGet routine takes a new opaque parameter of type sp *.
Compiling thus:
clang PutGetD.c -O3 -Sproduces this which reveals that the 2nd argument arrives in %rsi.
The new scheme amounts to each side of the routine passing around the stack-top handle of its partner as a hot-potato. (by which I mean that every stack frame of either side carries the address of where the stack-top of the other side is.) The initiator of the coroutine provides an 8 byte cell for an opaque value that is in fact the stack pointer of the side that is not running. Here is the slightly modified technology. The new interface to this is that a 2nd argument to both begin and PutGet is the address of the stack-top, which was abstracted in the one connection version.
The first argument to begin is passed on as the first argument to startR. Its meaning is up to the technology user. The second argument to begin is the address of a cell that holds the stack-top of the coroutine that is not running.
We compile and run thus:
clang main.c PutGet.s -O3 -Wmost ./a.outThat gives me:
Trees at 000FFFFE, 001FFFFD and 002FFFFC Whee! Different at E3D70which is about what I hoped for.
gcc mainLin.c PutGetLin.s -O3 -Wall -std=c99 ./a.outworks for me.
Perhaps first argument to PutGetR should not appear as begin’s value.
No stack overflow protection.
No test for malloc failure.