Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

continuations

Name: Anonymous 2013-03-02 2:18

In this thread, you may post code that makes use of continuations, and I will attempt to produce code that does the same and looks reasonably similar, without using continuations.

Name: Anonymous 2013-03-02 10:52

I suppose there are bugs in this, but you get the idea:

(define yield-to-event-loop (lambda () (error "not set")))

(define (main-loop)
  (dispatch (get-next-event))
  (main-loop))

(define (dispatch event)
  (cond
    ; Other internal and external events
    ; ...

    ((io-event? event)
     (let ((cont (get-io-continuation (get-io-ticket event))))
       (cont (get-io-data event))))

    ((resumable? event)
     ((get-resumable-continuation event)))

    (else (unhandled-event event))))

(define (resource-manager init n)
  ; Limited number of resources, for instance file descriptors
  (define resources (make-list-of-n-resources init n))
  (define wait-queue '())

  ; Return a free resource, and wait until there is one to get
  (define (get-resource)
    (call-with-current-continuation
      (lambda (k)
        (if (null? resources)
            (begin
              ; No free resource, resume caller later
              (set! waiters (cons k wait-queue))
              (yield-to-event-loop))
            (let ((resource (car resources)))
              (set! resources (cdr resources))
              resource)))))

  ; Free a single resource and possibly let a waiting event handler run
  (define (free-resource resource)
    (call-with-current-continuation
      (lambda (k)
        (if (null? wait-queue)
            (set! resources (cons resource resources))
            (let (waiter (car wait-queue))
              (set! waiters (cdr wait-queue))

              ; Suspend the caller for a while
              (push-resumable-event k)

              ; Resume a waiting event handler
              (waiter resource)))))
    #t)

  ; Return dispatcher
  (lambda (message)
    (case message
      ((get-resource) get-resource)
      ((free-resource) free-resource)
      (else (error "unknown message")))))

(define (read-from-io-device device)
  (call-with-current-continuation
    (lambda (k)
      (let (io-ticket (schedule-read device))
        (push-event-queue-io-continuation io-ticket k)
        (start-io-event io-ticket)
        (yield-to-event-loop)))))

(define io-manager (resource-manager make-io-port 4))

; Register some event handlers
(for-each
  (lambda (event)
    (register-event-handler event
      (lambda ()
        ; Here, without continuations, you end up with node.js
        ; get-resource, free-resource and read-from-io-device all
        ; yield to the event loop if necessary
        (let ((device ((io-manager 'get-resource))))
          (display (read-from-io-device device)
          ((io-manager 'free-resource) device))))))
  '(event-1 event-2 event-3))

; Start main loop
(begin
  (call-with-current-continuation (lambda (k) (set! yield-to-event-loop k)))
  (main-loop))

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List