[usocket-cvs] r531 - in usocket/trunk: . backend

Chun Tian (binghe) ctian at common-lisp.net
Mon Jul 5 09:03:05 UTC 2010


Author: ctian
Date: Mon Jul  5 05:03:05 2010
New Revision: 531

Log:
SBCL: commit untested WAIT-FOR-INPUT for win32.

Modified:
   usocket/trunk/backend/lispworks.lisp
   usocket/trunk/backend/sbcl.lisp
   usocket/trunk/usocket.lisp

Modified: usocket/trunk/backend/lispworks.lisp
==============================================================================
--- usocket/trunk/backend/lispworks.lisp	(original)
+++ usocket/trunk/backend/lispworks.lisp	Mon Jul  5 05:03:05 2010
@@ -604,7 +604,8 @@
   
   (fli:define-foreign-type ws-socket () '(:unsigned :int))
   (fli:define-foreign-type win32-handle () '(:unsigned :int))
-  (fli:define-c-struct wsa-network-events (network-events :long)
+  (fli:define-c-struct wsa-network-events
+    (network-events :long)
     (error-code (:c-array :int 10)))
 
   (fli:define-foreign-function (wsa-event-create "WSACreateEvent" :source)
@@ -669,9 +670,9 @@
           0))))
 
   (defun socket-ready-p (socket)
-     (if (typep socket 'stream-usocket)
-       (< 0 (bytes-available-for-read socket))
-       (%ready-p socket)))
+    (if (typep socket 'stream-usocket)
+        (< 0 (bytes-available-for-read socket))
+      (%ready-p socket)))
 
   (defun waiting-required (sockets)
     (notany #'socket-ready-p sockets))
@@ -686,29 +687,27 @@
     (let ((event-map (fli:foreign-slot-value network-events 'network-events))
           (error-array (fli:foreign-slot-pointer network-events 'error-code)))
       (unless (zerop event-map)
-	  (dotimes (i fd-max-events)
-	    (unless (zerop (ldb (byte 1 i) event-map)) ;;### could be faster with ash and logand?
-	      (funcall func (fli:foreign-aref error-array i)))))))
+        (dotimes (i fd-max-events)
+          (unless (zerop (ldb (byte 1 i) event-map)) ;;### could be faster with ash and logand?
+            (funcall func (fli:foreign-aref error-array i)))))))
 
   (defun update-ready-and-state-slots (sockets)
-     (dolist (socket sockets)
-        (if (or (and (stream-usocket-p socket)
-                     (listen (socket-stream socket)))
-                (%ready-p socket))
-            (setf (state socket) :READ)
-          (multiple-value-bind
-                (rv network-events)
-                (wsa-enum-network-events (os-socket-handle socket) 0 t)
-             (if (zerop rv)
-                 (map-network-events #'(lambda (err-code)
-                                         (if (zerop err-code)
-                                             (setf (%ready-p socket) t
-                                                   (state socket) :READ)
-                                             (raise-usock-err err-code socket)))
-                                     network-events)
-                 (maybe-wsa-error rv socket))))))
-
-
+    (dolist (socket sockets)
+      (if (or (and (stream-usocket-p socket)
+                   (listen (socket-stream socket)))
+              (%ready-p socket))
+          (setf (state socket) :READ)
+        (multiple-value-bind
+            (rv network-events)
+            (wsa-enum-network-events (os-socket-handle socket) 0 t)
+          (if (zerop rv)
+              (map-network-events #'(lambda (err-code)
+                                      (if (zerop err-code)
+                                          (setf (%ready-p socket) t
+                                                (state socket) :READ)
+                                        (raise-usock-err err-code socket)))
+                                  network-events)
+            (maybe-wsa-error rv socket))))))
 
   ;; The wait-list part
 

Modified: usocket/trunk/backend/sbcl.lisp
==============================================================================
--- usocket/trunk/backend/sbcl.lisp	(original)
+++ usocket/trunk/backend/sbcl.lisp	Mon Jul  5 05:03:05 2010
@@ -13,6 +13,10 @@
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (require :sockets))
 
+#+(and sbcl win32) ; for "WaitForSingleObject"
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (sb-alien:load-shared-object "kernel32.dll"))
+
 #+sbcl
 (progn
   #-win32
@@ -354,18 +358,15 @@
 
 #+(and sbcl (not win32))
 (progn
+  (defun %setup-wait-list (wait-list)
+    (declare (ignore wait-list)))
 
-(defun %setup-wait-list (wait-list)
-  (declare (ignore wait-list)))
-
-(defun %add-waiter (wait-list waiter)
-  (push (socket waiter) (wait-list-%wait wait-list)))
-
-(defun %remove-waiter (wait-list waiter)
-  (setf (wait-list-%wait wait-list)
-        (remove (socket waiter) (wait-list-%wait wait-list))))
-
+  (defun %add-waiter (wait-list waiter)
+    (push (socket waiter) (wait-list-%wait wait-list)))
 
+  (defun %remove-waiter (wait-list waiter)
+    (setf (wait-list-%wait wait-list)
+          (remove (socket waiter) (wait-list-%wait wait-list))))
 
   (defun wait-for-input-internal (sockets &key timeout)
     (with-mapped-conditions ()
@@ -398,8 +399,141 @@
                        (setf (state x) :READ))))))))))
 ) ; progn
 
+
+;;; WAIT-FOR-INPUT support for SBCL on Windows platform (Chun Tian (binghe))
+;;; Based on LispWorks version written by Erik Huelsmann.
+
 #+(and sbcl win32)
-  (warn "wait-for-input not (yet!) supported...")
+(progn
+  (defconstant fd-read 1)
+  (defconstant fd-read-bit 0)
+  (defconstant fd-write 2)
+  (defconstant fd-write-bit 1)
+  (defconstant fd-oob 4)
+  (defconstant fd-oob-bit 2)
+  (defconstant fd-accept 8)
+  (defconstant fd-accept-bit 3)
+  (defconstant fd-connect 16)
+  (defconstant fd-connect-bit 4)
+  (defconstant fd-close 32)
+  (defconstant fd-close-bit 5)
+  (defconstant fd-qos 64)
+  (defconstant fd-qos-bit 6)
+  (defconstant fd-group-qos 128)
+  (defconstant fd-group-qos-bit 7)
+  (defconstant fd-routing-interface 256)
+  (defconstant fd-routing-interface-bit 8)
+  (defconstant fd-address-list-change 512)
+  (defconstant fd-address-list-change-bit 9)
+  (defconstant fd-max-events 10)
+  (defconstant fionread 1074030207)
+
+  (sb-alien:define-alien-type ws-socket sb-alien:unsigned-int)
+
+  (sb-alien:define-alien-type nil
+    (sb-alien:struct wsa-network-events
+      (network-events sb-alien:long)
+      (error-code (array sb-alien:int 10)))) ; 10 = fd-max-events
+
+  (sb-alien:define-alien-routine ("WSACreateEvent" wsa-event-create)
+      sb-alien::hinstance) ; return type only
+
+  (sb-alien:define-alien-routine ("WSACloseEvent" wsa-event-close)
+      (sb-alien:boolean #.sb-vm::n-machine-word-bits)
+    (event-object sb-alien::hinstance))
+
+  (sb-alien:define-alien-routine ("WSAEnumNetworkEvents" wsa-enum-network-events)
+      sb-alien:int
+    (socket ws-socket)
+    (event-object sb-alien::hinstance)
+    (network-events (* (sb-alien:struct wsa-network-events))))
+
+  (sb-alien:define-alien-routine ("WSAEventSelect" wsa-event-select)
+      sb-alien:int
+    (socket ws-socket)
+    (event-object sb-alien::hinstance)
+    (network-events sb-alien:long))
+
+  (sb-alien:define-alien-routine ("WaitForSingleObject" wait-for-single-object)
+      sb-alien:long
+    (object sb-alien::hinstance)
+    (timeout sb-alien:long))
+
+  (defun maybe-wsa-error (rv &optional socket)
+    (unless (zerop rv)
+      (raise-usock-err (sockint::wsa-get-last-error) socket)))
+
+  (defun os-socket-handle (usocket)
+    (socket usocket))
+
+  (defun bytes-available-for-read (socket)
+    (sb-alien:with-alien ((int-ptr sb-alien:long))
+      (let ((rv (sockint::win32-ioctl (os-socket-handle socket) fionread int-ptr)))
+        (prog1
+            (if (= 0 rv) (sb-alien:deref int-ptr) 0)
+          (sb-alien:free-alien int-ptr)))))
+
+  (defun socket-ready-p (socket)
+    (if (typep socket 'stream-usocket)
+        (< 0 (bytes-available-for-read socket))
+      (%ready-p socket)))
+
+  (defun waiting-required (sockets)
+    (notany #'socket-ready-p sockets))
+
+  (defun wait-for-input-internal (wait-list &key timeout)
+    (when (waiting-required (wait-list-waiters wait-list))
+      (maybe-wsa-error
+       (wait-for-single-object (wait-list-%wait wait-list) (truncate (* 1000 timeout)))
+       wait-list))
+    (update-ready-and-state-slots (wait-list-waiters wait-list)))
+
+  (defun map-network-events (func network-events)
+    (let ((event-map (sb-alien:slot network-events 'network-events))
+          (error-array (sb-alien:slot network-events 'error-code)))
+      (unless (zerop event-map)
+        (dotimes (i fd-max-events)
+          (unless (zerop (ldb (byte 1 i) event-map)) ;;### could be faster with ash and logand?
+            (funcall func (sb-alien:deref error-array i)))))))
+
+  (defun update-ready-and-state-slots (sockets)
+    (dolist (socket sockets)
+        (if (or (and (stream-usocket-p socket)
+                     (listen (socket-stream socket)))
+                (%ready-p socket))
+            (setf (state socket) :READ)
+          (multiple-value-bind
+              (rv network-events)
+              (wsa-enum-network-events (os-socket-handle socket) 0 t)
+            (if (zerop rv)
+                (map-network-events #'(lambda (err-code)
+                                        (if (zerop err-code)
+                                            (setf (%ready-p socket) t
+                                                  (state socket) :READ)
+                                          (raise-usock-err err-code socket)))
+                                    network-events)
+              (maybe-wsa-error rv socket))))))
+
+  (defun %setup-wait-list (wait-list)
+    (setf (wait-list-%wait wait-list) (wsa-event-create))
+    (sb-ext:finalize wait-list
+                     #'(lambda () (unless (null (wait-list-%wait wait-list))
+                                    (wsa-event-close (wait-list-%wait wait-list))))))
+
+  (defun %add-waiter (wait-list waiter)
+    (let ((events (etypecase waiter
+                    (stream-server-usocket (logior fd-connect fd-accept fd-close))
+                    (stream-usocket (logior fd-connect fd-read fd-oob fd-close))
+                    (datagram-usocket (logior fd-read)))))
+      (maybe-wsa-error
+       (wsa-event-select (os-socket-handle waiter) (wait-list-%wait wait-list) events)
+       waiter)))
+
+  (defun %remove-waiter (wait-list waiter)
+    (maybe-wsa-error
+     (wsa-event-select (os-socket-handle waiter) (wait-list-%wait wait-list) 0)
+     waiter))
+) ; progn
 
 #+ecl
 (progn
@@ -423,5 +557,4 @@
 
   (defun %remove-waiter (wl w)
     (declare (ignore wl w)))
-
-  )
+) ; progn

Modified: usocket/trunk/usocket.lisp
==============================================================================
--- usocket/trunk/usocket.lisp	(original)
+++ usocket/trunk/usocket.lisp	Mon Jul  5 05:03:05 2010
@@ -35,7 +35,7 @@
 
 The last two remain unused in the current version.
 ")
-   #+(and lispworks win32)
+   #+(and win32 (or sbcl lispworks))
    (%ready-p
     :initform nil
     :accessor %ready-p




More information about the usocket-cvs mailing list