> [ long win32 proposal ]
> 
> I've to read through that some more times.

OK; let me know if you have any questions on how the Win32 stuff
works. I tried to explain things that are unlike POSIX, but of course
it makes sense to me.

> Do you alread have ideas for a common API, or where to split the
> existing threads.c into platform and common code?

I didn't see anything in thread.c that was platform specific -- or at
least nothing that looked like it wouldn't work on Win32. Obviously
thr_win32.h will be much different than thr_pthreads.h.

As for a common API, I suppose we would have to figure out how the
modules would interact. In the case of IO (any function names I made
up have capital letters to distinguish them from anything that may be
in the current codebase):

* There is some generic IO code that sets up IO and event objects, and
it sits below the buffering layer. All this stuff is going to be
thread-safe so the low-level IO code shouldn't have to worry about it.
This generic IO code sets up the IO and Event objects indicating what
file, which operation (read/write/lock/unlock), what to do when the
operation completes, how many bytes, file position, and any memory
buffer needed. Then it would pass this information to the OS-specific
code.

So this generic code (say, StartIO()) would create an IO object that
contains the file object, a pointer to the r/w buffer if the operation
requires it, and a file position and byte count if the operation uses
it. It would also contain an event object indicating what to do in
case of failure or completion. StartIO pins the memory buffer, locks
the IO object, and calls Win32AsyncRead or whatever.

The XXXAsyncYYY funtcion starts the IO and returns to StartIO which
unlocks the IO object and returns it to the caller. That can then be
passed into functions to find out if it's complete, cancel it, etc.

If XXX is Win32, the module would just start Read/WriteFile; if it's
Solaris, maybe it'll call aioread/write; if it's POSIX without aio
(e.g. Linux), it'll start up a new thread to do a blocking read/write.

When the IO completes, the XXX code figures out the return code and
how many bytes read/written. This information is passed to the generic
CompleteIO(), which locks the IO object, updates the status (return
code, byte count), unpins the buffer, dispatches the event as
described by the Event object, and unlocks the IO object.

* In the case of timers, there would be XXXCreateTimer and
XXXCancelTimer, while the XXX code would need to call FireTimer().

* I suppose there should be an XXXQueueEvent function as well, but I'm
not certain of its uses. Actual EventDispatch() would be a generic
function that puts an event into a thread's queue and notifies the
thread. I am not sure how to handle general events like RunGC.

* GUI message handlers need to dispatch events synchronously. So the
generic check_events function would call XXXGetGUIMessages which would
need to dispatch the messages to whatever registered for them in that
thread. Since this would amount to method dispatch instead of event
dispatch, it would probably need something special for this.

GNS

Reply via email to