Article 59980 of comp.os.vms:
Path: jac.zko.dec.com!pa.dec.com!decwrl!genmagic!rahul.net!a2i!news.clark.net!news.sprintlink.net!hookup!news.mathworks.com!mvb.saic.com!info-vax
From: Jerry Leichter <leichter@lrw.com>
Newsgroups: comp.os.vms
Subject: RE: tcp/ip, signals and queues
Message-ID: <9504301400.AA08419@uu3.psi.com>
Date: Sun, 30 Apr 95 09:53:27 EDT
Organization: Info-Vax<==>Comp.Os.Vms Gateway
X-Gateway-Source-Info: Mailing List
Lines: 112

	>> My recommendation to you, like my recommendation to them:  Try to
	>> do things the way that's natural for the system you are using.
	>> Signals are not AST's.

	Well thanks for that... your advice is 'do it the way it should be
	done'.  As I said, we have little Unix experience. I would appreciate
	some pointers here! 

	>> While you can more or less write Unix programs in a VMS AST-driven
	>> style, you'll find yourself fighting Unix all the way.  You're
	>> likely to do better using a pseudo-polling style of programming,
	>> based on the select() call.  That's what it's there for.

	Polling was considered originally, but the whole point is that we want
	to react to a message as soon as it becomes available (i.e. not on the
	next poll), so we need asynchronous notification of the availability
	of data.  Are you saying that there is no way to do this on Unix?

select() allows your polling loop to stall exactly until data becomes avail-
able.  A Unix polling loop looks like:

	while (1)
	{	select(...);
		while (more_events)
		{	switch (event_that_occurred)
			{
		case A:
			...
		case B:
			...
			}
		}
	}

This is equivalent to the VMS:

	enable_AST_for_interesting_events(&handler);
	while (1)
	{	SYS$HIBER();

		while (more_events)
		{	switch (event_that_occurred)
			{
		case A:
			...
		case B:
			...
			}
		}
	}

	handler()
	{
		record_event;
		SYS$WAKE(0,0);
		re-enable_AST(&handler);
	}

The way you check for "more_events" and pick "event_that_occurred" differs in
the two cases.  In Unix, the arguments to select() are (mainly) addresses of
bit masks representing file descriptor; 1 bits indicate descriptors you are
interested in.  The bit masks are altered by the select() call so that on
return, 1 bits represent descriptors for which the requested event (data ready
to read, data write completed, exception) occurred.  You have to go do the
read() or write() or whatever yourself, but you can be sure it won't block.

In VMS, you code the "more_events" and "event_that_occurred" stuff yourself;
also, the AST occurs *after* the read or write has completed - so the cases
look different for the two OS's.  But the basic structure is the same.

Note that this style of VMS coding, while common and workable, is not all you
can do in the VMS case.  There are at least two things you can do easily in
VMS which don't translate easily:

	1.  Do some work in the AST handler, rather than just waking the
		mainline code.  For example, start the next $QIO.  (This
		has no direct analogue because in the Unix case the I/O
		hasn't yet completed - you have to do the read() or whatever
		in the main line anyway, and any re-enabling that has to be
		done is implicit in the select() call.)  Really high-perfor-
		mance VMS code lets the AST handler do the basic work of
		reception of data (say), putting the data that arrived on a
		queue and allocating a new buffer to start another read as
		fast as possible.  This style of programming isn't common on
		Unix, and is in fact almost impossible to accomplish.  Unix
		programs assume the kernel will buffer data for them; they
		typically do not double-buffer - no surprise, since up until
		recently there was no asynchronous I/O capability in Unix!

	2.  select() can only wait for events that occur on file descriptors.
		Message queues are not file descriptors, and can't be waited
		on by select().  If you need to wait for either a message to
		arrive, or for an I/O event to complete, you have to really
		poll, using msgrcv() with the IPC_NOWAIT parameter and
		select() with a timeout.  select() can also, of course, be
		interrupted by receipt of a signal - not that that helps with
		message queues, since there is no way I know of to request
		that a signal be delivered when a message arrives.
		
Note that the above applies to "generic" Unix - really generic, actually,
since select() came from BSD and message queues from System V.  (Most systems
these days include both, but as (2) points out, they really aren't integrated
with each other.)  Some Unix vendors - in particular, those interested in the
real-time market - have of necessity added new system calls to Unix to provide
better support for this kind of programming.  There is also a set of Posix
"real time extensions" which promise to (finally) provide a portable set of
services.  I don't know how widely they've been implemented; it didn't help
that there was an apparently-stable draft spec out for a while that some
vendors (DEC, in VMS Posix, was one example) coded to - and then the next
version of the spec changed *everything* in an incompatible way.

							-- Jerry


