#lang scheme

(define-struct failure (exn))

(define (channel-get-values channel)
  (let ([result (channel-get channel)])
    (if (failure? result) (raise-user-error "Channel couldn't get because" (failure-exn result))
        (apply values result))))

(define (channel-put-values channel . values)
  (channel-put channel values))

(define (channel-raise channel e) 
  (let ([f (make-failure e)])
    (sync/timeout 3 (channel-put-evt channel f))))

; if we are putting (put-ing) to a channel
; we must do it in this context, so if something
; goes wrong, the channel-get-values can error out
; too. This expression means "in this context we
; guarantee that either a channel will be putted to
; as much as expected, or it will error out on get."

(define (channel-putting channel proc)
   (λ (e) (channel-raise channel e) e)
   (λ () (proc (λ values (channel-put channel values))))))

(provide (rename-out 
          (channel-get-values get)
          (channel-put-values put)
          (channel-raise raise)
          (channel-putting putting)))