Bert Freudenberg wrote:
Hi folks,
I'm implementing tablet support for X. This usually works by using XOpenDevice to, well, open the device, and then handling Device* events in the main loop.
So I need to install an event handler in the main HandleEvent loop. Which is sorta difficult to do from a module (JoystickTabletPlugin in this case). It's not even easy to get at the stDisplay connection, which is a global in sqXWindow.
Take a look at how SocketPlugin & SoundPlugin do it (well, the sqUnixBlahBlah files for those plugins) - basically you can set a global var in the moduleInitialise and (ab)use the ability of the linker to connect it properly. Check the aioPoll in sqXWindow.c to see how the polling is then done. Personally I prefer to have a callback function (that's what the examples in the default 'platforms.export' illustrate) to do this simply because it feels cleaner. Ian prefers the direct approach.
The disadvantage is that you still have to modify the sqXWindow.c to add the call to the function; some time ago there was some discussion about how to register functions for this stuff, but since sockets and sound (the two current usages) require quite different arguments it seemed to be a bit tricky. I guess it might be useful to have the general registry you suggest for most cases and perhaps accept that sockets can't work that way.
tim
Tim Rowledge wrote:
The disadvantage is that you still have to modify the sqXWindow.c to add the call to the function; some time ago there was some discussion about how to register functions for this stuff, but since sockets and sound (the two current usages) require quite different arguments it seemed to be a bit tricky. I guess it might be useful to have the general registry you suggest for most cases and perhaps accept that sockets can't work that way.
Well, if we want: * asynch file operations * event-driven serial I/O
we'll have to come up with something a little more general.
We have three general patterns here:
(1) we are waiting for I/O to complete.
Under Unix, we can use SIGIO or select(). There is an additional complication that under Unix, socket handles and/or file handles can be mixed in select calls.
Unfortunately, under Win32, select only works on sockets, and there's a different API for async file I/O. However, as I recall, you can get callbacks when I/O completes.
My main concern is ioRelinquishProcessor, which has to sleep for a while. It obviously would be better if this could be waken up by socket or other I/O activity.
The current function void aioPollForIO(int microSeconds, int extraFd) can be passed only a single extra file descriptor; this doesn't allow us to break out of the delay when, say, serial I/O happens. The extra Fd is, as I recall, being used for X communications.
I would prefer the ability to register a file handle (and/or socket) for monitoring and callback when I/O completes. This could be made transparent from the plugin's point of view. And it would allow Unix to use a single select() call for everything (though select calls with no timeouts are fine).
Some time ago Lex Spoon suggested: ---- How about doing it this way. The sleep routine is in the *main* part of the Unix VM, and the socket routines can register file descriptors that should interrupt the sleep. Basically, make the socket sleep routine more generic and move it out of the sockets plugin.
The main difficulty is that when you load the sockets plugin, the sockets plugin needs to be able to access the fd-registration functions over in the main VM. I dunno exactly how the plugins stuff works; would it be okay for a plugin to just directly call functions in the main VM, or do we need to pass those functions as parameters? If the latter, is there space in the initializeModule() routine for adding the backpointer to those functions?!
Note, by the way, that other plugins might want to register file descriptors like this, as well. For example, the sound module should really work this way. So it's not just a bad feeling that many of us get about giving the sockets plugin special treatment--it can cause real trouble down the line. ----
(2) we need an arbitrary callback into a plugin for some reason.
For instance, if some kind of periodic checking was needed. Some hardware support (bare hardware or dumb drivers) may require this.
Again, a different kind of registration would work; this would be passed a void* and then just call the registered functions in the main loop, passing them back their void*.
(3) plugins need to hook X events
Bert's suggestion:
Or, we could invent a general callback list where plugins could hook into the main loop (and startup/shutdown functions). Something like
struct { int (*init)(Display*, Window); int (*handle)(XEvent*); int (*shutdown)(); } hooks[];
Forgive me if I am overlooking something really obvious, but while we're almost on the topic, what is it prevents one from doing ordinary message sends from C code by having the equivalent of the exact bytecodes of a message send as a sequence of (Slang-generated) C code? This is what I thought that exception code was doing when it triggers a method for block unwinding or something.
Is it something like the interpreter not being reentrant?
Henrik
Henrik Gedenryd Henrik.Gedenryd@lucs.lu.se is widely believed to have written:
Forgive me if I am overlooking something really obvious, but while we're almost on the topic, what is it prevents one from doing ordinary message sends from C code by having the equivalent of the exact bytecodes of a message send as a sequence of (Slang-generated) C code? This is what I thought that exception code was doing when it triggers a method for block unwinding or something.
Kind of, yes. It does it in a very specific situation and the image code never returns to that C code routine. As Andreas said, just try returning through a C stackframe!
tim
squeak-dev@lists.squeakfoundation.org