Tue Nov 21 13:01:25 EST 2006


it really shouldn't be so hard to make output tasks = anything that's
waiting for a file descriptor = OS I/O. what form would this take?
currently i have things stored as 'stream + stuff list'. the necessary
information is this:

* stream
* input/output/error
* task (DS RS)

there's one problem atm: blocking reads/writes can not be handled in C
code, unless i use some kind of setjmp method to jump back to the
interpreter. best of all is to avoid the C stack entirely and do the
scheduling incrementally.

so, the scheduler should be 
* round-robin, in case it's not tied to an OS stream
* use select in case it is.

currently pf_vm_idle() is used in
- PF_PRIMITIVE(pf_word_read_thing) (called by ..read_atom)
- pf_vm_stream_write()
- pf_vm_stream_read()

blocking I/O is used when writing directly to a stream. the blocking
loop itself is handled in C: pf_vm_idle() can eventually be called
from pretty deep in the C stack, so I don't want to do any stuff there
that can make it blow up.

what i want is 'blocking I/O on the forth level' which means: do a
non-blocking OS read/write, and save the task in a list whenever it's
not done. during C level blocking I/O, only buffered packet write can
be used.

hmm.. that's clumsy.

what i need is to exactly know when the scheduler pf_vm_idle() is
invoked. this should not happen during printing.. 

another question: what can be done when blocking I/O is used in
'single thread mode'. just like the parser, the printer should be
pre-emptable too.

the easiest way to do that is to always print to string first, then to
a pre-emptable single write.

so, i just wrote this in print.c:

there are 2 regimes here..

  * printing to string will never block.. use this in conjunction with
    non-blocking write to have non-blocking print.

  * printing directly to a non-string stream can block. the idle time
    is filled up with low level tasks (see select.c)

the thing is, i don't want to give up the latter part. or at least, i
don't want to really thing about how to do that. maybe it's better to
go for it anyway, write all the 'single threaded' blocking print code
explicitly as locally looped code. basicly, i need to rewrite printf
everywhere again..

pff.. again a large chunk of work. but it should be better when it's
done: printing can be done in well-deligned chunks, and non-blocking
IO handling then only works with simple write semantics, instead of
nested printfs.

OK. first part is done. now the blocking points are nicely separated
out, but i still need to write them.


that's what i need to do proper task switching: need to restart the
current execution token. this means vm->current to data stack and call

seems to work out for writing (without testing) added explicit
schedule support to pf_vm_t/forth.c

need to do the same for reading of course. adding chunk read support
to the parser. OK that seems to work now, on to writing.

seems everything's in place now.. check select.c again

ok, now the poller C code could be replaced by forth code. the
scheduler could be a true select scheduler + a bag of things to poll
once ever X ms.


reused e_yield to signal rescheduling event to the interpreter loop,
instead of a pf_vm_schedule() function, to make sure the current
function will exit. there are only a couple of blocking points atm:
read/write and sleep.