[comp.sys.next] Read timeouts in threads

wiml@milton.u.washington.edu (William Lewis) (02/17/91)

   I'm not quote sure if this is a NeXT question or a Mach question
(probably a Mach question) but here goes...

   I'm trying to get a (small amount of data) from the serial port
on the NeXT, /dev/cu?. Most of the time there should be something there
within a few milliseconds, but in the event that read() blocks for 
much time, I want to wake up and report this as an error. This would
be fairly easy in 'normal unix' using a timer and signals, or using
select, but this is in a thread in Mach. The thread is supposed to keep
a low profile & allow the "main" thread to act as if it were the only
thread around (ie. no mutexes, etc.). Unfortunately, I hear that signals
don't mix well with Mach threads...  So far I can think of two
possibilities other than doing non-blocking reads and busy looping
(yeccchhh):
  
    1. Make yet another thread whose sole purpose is to sit around and
make sure that the thread in question doesn't block too long, say,
by waiting for "I'm alive" messages on a certain port and timing out
and performing thread_kills if one doesn't come in time.
    2. Again, have another thread, but this one blocks reading the serial
port, and sends a mach message to the first thread when it gets something.
The first thread can use RCV_TIMEOUT and wake up after a while.

    But both of these seem needlessly complex (a whole thread just to
allow me to time out a read()??????). Is there some better way to
interrupt a blocked read() after a specified interval? Any help
is much appreciated ...
-- 
 wiml@milton.acs.washington.edu       Seattle, Washington   
     (William Lewis)   |  47 41' 15" N   122 42' 58" W  
 "Just remember, wherever you go ... you're stuck there."

eps@toaster.SFSU.EDU (Eric P. Scott) (02/18/91)

In article <16593@milton.u.washington.edu>
>                                                          This would
>be fairly easy in 'normal unix' using a timer and signals, or using
>select, but this is in a thread in Mach.

Please explain why select() is unsuitable.

					-=EPS=-

tim@ohday.sybase.com (Tim Wood) (02/21/91)

In article <16593@milton.u.washington.edu> wiml@milton.u.washington.edu (William Lewis) writes:
>
>   I'm trying to get a (small amount of data) from the serial port
>on the NeXT, /dev/cu?. Most of the time there should be something there
>within a few milliseconds, but in the event that read() blocks for 
>much time, I want to wake up and report this as an error. 

Does NeXT have the select() system call?  That allows a blocking poll
for I/O with a timeout, which seems to be what you want.
-TW



Sybase, Inc. / 6475 Christie Ave. / Emeryville, CA / 94608	  415-596-3500
WORK:tim@sybase.com     {pacbell,pyramid,sun,{uunet,ucbvax}!mtxinu}!sybase!tim
PLAY:axolotl!tim@toad.com		       {sun,uunet}!hoptoad!axolotl!tim
Dis claim er dat claim, what's da difference?  I'm da one doin da talkin' hea.

preston@LL.MIT.EDU (Steven Preston) (02/21/91)

> In article <12395@sybase.sybase.com> tim@ohday.sybase.com (Tim Wood) writes:
>>Does NeXT have the select() system call?

> I have thought of two solutions
> 1.  Using Unix's alarm and signal.
> 2.  Read only when there is data in the serial port.  [Use DPSAddFD]

NeXT DOES have a select() system call.  There is no need to kludge
with the alarms and signals of (1).  If you are working on an appkit
application then (2) is the easiest way to go.  OTOH, if you are
working on a traditional UNIX filter-type app, then you would probably
want to use select().

I have written a class, called Fdset (for file descriptor set), which
can be used to register any number of file descriptors and will wait
for input with or without timing out.  Here is the Fdset.h file.
------------------------------------------------------------------------
#import <sys/types.h>
#import <objc/Object.h>

@interface Fdset:Object
{
  fd_set fds;        // holds the file descriptors this set will wait on
  fd_set ready_fds;  // holds only those file descriptors which are ready for reading
  int nfds;          // the largest fd in the set plus 1
}

+ new;
- addfd:(int)thisfd;
- (BOOL) isfdReady:(int)thisfd; // returns YES if given descriptor is ready
- (int) waitOnInputForever;  // returns number of file descriptors which are ready
- (int) waitOnInputFor:(int)seconds;  //waits no more than number of seconds
- (int) waitOnInputFor:(int)seconds :(int)microseconds;  // for fractional timeouts
- (int) getReadyfd;  //returns one of the ready file descriptors, marks it unready

@end
------------------------------------------------------------------------
It is trivial to write the methods, after reading the select man page.
--
Steve Preston