Welcome, Guest! Log In | Create Account

Unix select usage

From ecls

Jump to: navigation, search
;; The following is a straight port if the example in the Linux
;; select(2) manpage to the ECL FFI.

(defpackage "select-test"
  (:use "CL" "FFI" "UFFI"))
(in-package "select-test")

(clines "#include <sys/select.h>")

(defun fdset-size ()
  (c-inline () () :int "sizeof(fd_set)" :one-liner t :side-effects nil))

(defun select (infds)
  ;; fd_set is an opaque typedef, so we can't declare it locally.
  ;; However we can find out its size and allocate a char array of
  ;; the same size which can be used in its place.
  (let ((fsize (fdset-size)))
    (with-foreign-object (rfd `(:array :unsigned-char ,fsize))

      ; Reset fd sets
      (c-inline (rfd) (:object :object) :void
                "{ FD_ZERO(#0->foreign.data); }"
                :one-liner nil
                :side-effects t)

      ; ... and initialise them
      (dolist (fd infds)
        (c-inline (fd rfd) (:int :object) :void
                  "{ FD_SET(#0, (fd_set*)#1->foreign.data); }"
                  :one-liner nil
                  :side-effects t))

      ; Do select wait
      (let ((retval
             (c-inline (rfd) (:object :object) :int
                "{ struct timeval tv;
                   tv.tv_sec = 5;
                   tv.tv_usec = 0;
                   @(return) = select(1, #0->foreign.data, NULL, NULL, &tv); }"
                  :one-liner nil
                  :side-effects t)))
        ; check return type
        (case retval
          (-1 (format t "error~%"))
          (0 (format t "no data in 5 seconds~%"))
          (otherwise (format t "Data available~%")))))))

;; Quick test code on (load ..)
(format t "fd_set is ~A~%" (fdset-size))
(select '(0))