Jump to content
Excelsior Forums
qnr

Anyone know how I can get select working?

Recommended Posts

Does anyone have any experience with sockets in XDS Modula-2?  I have a program that does pretty much what I need.  However, I have to set read to non-blocking and continuously poll.  As you can imagine, this eats up the CPU time.

I'm not really very familiar with C - so when I look at the select man page, some of what they assume I know goes right over my head.

Here is an example from Beej's Guide to Network Programming at http://www.ecst.csuchico.edu/~beej/guide/net (note that this isn't using sockets, just showing how to use select).

[tt]#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

#define STDIN 0  /* file descriptor for standard input */

main()

{

    struct timeval tv;

    fd_set readfds;

    tv.tv_sec = 2;

    tv.tv_usec = 500000;

    FD_ZERO(&readfds);

    FD_SET(STDIN, &readfds);

    /* don't care about writefds and exceptfds: */

    select(STDIN+1, &readfds, NULL, NULL, &tv);

    if (FD_ISSET(STDIN, &readfds))

        printf("A key was pressed!\n");

    else

        printf("Timed out.\n");

}

[/tt]

I'm trying to use Peter Moylan's PMOS sockets.def (Written for OS/2 I believe) as a starting point, but no matter what I do, I get a -1, which indicates an error.  Here is Peter's code for select:

[tt]TYPE Socket = CARDINAL;[/tt]

[ ... snipped ... ]

[tt]PROCEDURE ["SysCall"] select (VAR (*INOUT*) group: ARRAY OF Socket;

                          NumberOfReads, NumberOfWrites, NumberOfExcepts: CARDINAL;

                          Timeout: CARDINAL): INTEGER;

    (* Waits until one or more of the sockets in "group" is ready.  The next    *)

    (* three parameters specify how many sockets are in the array.  The sockets *)

    (* to be checked for input come first, then the ones to be checked for      *)

    (* output, then the ones to be checked for exceptional conditions.  The    *)

    (* Timeout value is in milliseconds, except that a value of MAX(CARDINAL)  *)

    (* means "wait forever".  If one or more of the sockets are ready when this *)

    (* function returns, the return value is the number of ready sockets, and  *)

    (* the entries in group corresponding to not-ready sockets are reset to    *)

    (* the value NotASocket.  A return value of 0 indicates timeout.  A return  *)

    (* value of -1 means error.                                                *)

[/tt]

I can't get that to work (using ["C"] / instead of ["SysCall"] and the appropriate pragmas to use C function calls.

Can anyone show me how to get this working?

qnr

Edit: Fixed some problems with the cut & pasted code.

Share this post


Link to post
Share on other sites

OK, I kind of have select working, after following some code done up for Atari STs. 

Now, I'd like to know if anyone can help me with calling

FD_SET, FD_CLR, FD_ZERO and FD_ISSET

If I try to call them using (for example):

[tt]

TYPE Socket = CARDINAL;

  WORDSETRANGE = [0..15];

  WORDSET = SET OF WORDSETRANGE;

  fdSet = ARRAY [0..MAXFDSET] OF WORDSET;

  FdSetPtr = POINTER TO fdSet;

...

PROCEDURE ["C"] / FD_SET ( fd : INTEGER;

                          VAR fdset : FdSetPtr );

...

  FD_SET(rfds); (* This is line 89 *)[/tt]

I get an:

* [select.mod 89.03 E020]

* undeclared identifier "FD_ZERO"

  $FD_ZERO(rfds);

Share this post


Link to post
Share on other sites

Well, just as an update - I've temporarily given up on select() since I'm not familiar enough with C - however, it looks like I have poll() working ... though I haven't tried it with any socket related programs yet.

Share this post


Link to post
Share on other sites

another update:  It turns out that poll() was much easier for me to understand, so I'm using this, and it works great.

<* M2EXTENSIONS + *>
<* M2ADDTYPES + *>
<*+ CSTDLIB  *>
<*+ NOHEADER  *>

IMPORT SYSTEM; (* Might not technically be necessary, because of the pragmas *)

CONST
  POLLIN   = 1;
  POLLPRI  = 2;
  POLLOUT  = 4;
  POLLERR  = 8;
  POLLHUP  = 16;
  POLLNVAL = 32;

TYPE 
  nfds_t = LONGCARD;

  pollfd = RECORD
    fd     : SYSTEM.int;    (*  File descriptor to poll.   *)
    events : SYSTEM.INT16;  (*  Types of events poller cares about.   *)
    revents: SYSTEM.INT16;  (*  Types of events that actually occurred.   *)
  END;

  Ptrpollfd = POINTER TO pollfd;

VAR
  bittest : BITSET;
  return  : INTEGER;
  tout    : int;
  fd      : pollfd;
  nfds    : nfds_t;

PROCEDURE ["C"] / poll ( fds: Ptrpollfd; nfds: nfds_t;
                         timeout: SYSTEM.int ): SYSTEM.int;

BEGIN
   
  nfds := 1;
  tout := 50; (* timeout value for poll() in milliseconds *)


  fd.fd := serv; (* server, obtained earlier, but not shown *)
  fd.events := CAST(SYSTEM.INT16, POLLIN+POLLPRI);
  fd.revents := CAST(SYSTEM.INT16, 0);
  return := poll( fd, nfds, tout);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×