From: skaller <sk...@us...> - 2005-10-31 04:38:14
|
I am now looking at adding a synchronous channel concept. This is related to RF's Asych I/O stuff, however the implementation here will be for a *synchronous* channel. Roughly the design is: type schan = "..."; fun mk_chan: 1 -> schan = " .. "; proc reader(mychan: schan) { var data: string; svc_sread (schan,&data); .... } mychan := mk_chan(); spawn { reader mychan; }; svc_write (mychan, "Hello"); Channels buffer a single write object. Both reads and writes are blocking operations which causes the thread to suspend: A read suspends until there is something to read, the continuation of the reader clears the buffered object. A write suspends until the channel is clear, stores the object, and suspends again until it is clear. This design can deadlock or die of starvation. Flx_run should probably detect this, in general however it will not be possible. In particular, when some threads wait on external events -- that is, with asychronous event sources -- it isn't so easy to detect lockups (since the driver doesn't know anything about the external event source). BTW: I think it was Wirth that invented this algorithm, the kind of channel described here is called a *monitor*. Monitors work for pre-emptive threading too. Along with synchronous channel I/O it is possible to add some meaningful features: kill, wait, join, locks, and a few other common primitives (which make no sense without some kind of communication). BTW: you may ask about broadcast channels etc. The basic design transfers a single object from one thread to another. Any number of threads and write to a channel 'at once'. One will be chosen at random to go first. Same for reads. To implement broadcasting an application will have to invent a subscription service. One thread will do the reading, then COPY the object to a list of subscriber channels. Who gains access to a channel is determined by the code that creates it: initially only the creator has access. Channels will be garbage collected like other system objects. A typical use of a channel will be to spawn an fthread which does *asynchronous* I/O, and reads or write the data to or from the synchronous channel. In this way, the application can hand the synchronous channel to a subcomponent which has no need of knowing if the data it is reading/writing is going to another fthread .. or to a TCP/IP port. Buffered channels can be implemented on top of channels. Finally idea .. there is a need to write several things to a channel in sequence .. and not have anyone else interfere .. this is an atomic transaction idea .. this could be done with (b)locks. However it could also be done with transactional memory as described in the composeable memory paper. -- John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net |