- (when usable
- (return t))
-
- (when timeout
- (multiple-value-bind (okay sec usec) (sb!unix:unix-gettimeofday)
- (declare (ignore okay))
- (when (or (> sec stop-sec)
- (and (= sec stop-sec) (>= usec stop-usec)))
- (return nil))
- (setq to-sec (- stop-sec sec))
- (cond ((> usec stop-usec)
- (decf to-sec)
- (setq to-usec (- (+ stop-usec 1000000) usec)))
- (t
- (setq to-usec (- stop-usec usec))))))))))))
+If SERVE-EVENTS is true (the default), events on other FDs are served while
+waiting."
+ (tagbody
+ :restart
+ (multiple-value-bind (to-sec to-usec stop-sec stop-usec signalp)
+ (decode-timeout timeout)
+ (declare (type (or integer null) to-sec to-usec))
+ (flet ((maybe-update-timeout ()
+ ;; If we return early, recompute the timeouts, possibly
+ ;; signaling the deadline or returning with NIL to caller.
+ (setf (values to-sec to-usec)
+ (relative-decoded-times stop-sec stop-usec))
+ (when (and (zerop to-sec) (not (plusp to-usec)))
+ (cond (signalp
+ (signal-deadline)
+ (go :restart))
+ (t
+ (return-from wait-until-fd-usable nil))))))
+ (if (and serve-events
+ ;; No timeout or non-zero timeout
+ (or (not to-sec)
+ (not (= 0 to-sec to-usec)))
+ ;; Something to do while we wait
+ (or *descriptor-handlers* *periodic-polling-function*))
+ ;; Loop around SUB-SERVE-EVENT till done.
+ (dx-let ((usable (list nil)))
+ (dx-flet ((usable! (fd)
+ (declare (ignore fd))
+ (setf (car usable) t)))
+ (with-fd-handler (fd direction #'usable!)
+ (loop
+ (sub-serve-event to-sec to-usec signalp)
+ (when (car usable)
+ (return-from wait-until-fd-usable t))
+ (when to-sec
+ (maybe-update-timeout))))))
+ ;; If we don't have to serve events, just poll on the single FD instead.
+ (loop for to-msec = (if (and to-sec to-usec)
+ (+ (* 1000 to-sec) (truncate to-usec 1000))
+ -1)
+ when (or #!+win32 (eq direction :output)
+ (sb!unix:unix-simple-poll fd direction to-msec))
+ do (return-from wait-until-fd-usable t)
+ else
+ do (when to-sec (maybe-update-timeout))))))))