racket-ssh-2012/ordered-rpc.rkt

61 lines
1.8 KiB
Racket

#lang racket/base
;; Issue requests in order, process them in any order (or in
;; parallel), reassemble the ordering at the end.
;; What I'm doing here reminded me of the signal-notification
;; mechanism from [1], but is actually quite different.
;;
;; [1] O. Shivers, "Automatic management of operating-system
;; resources," in Proceedings of the Second ACM SIGPLAN International
;; Conference on Functional Programming (ICFP '97), 1997, vol. 32,
;; no. 8, pp. 274-279.
(require "functional-queue.rkt")
(provide make-transaction-manager
transaction-manager?
open-transaction
close-transaction!
transaction-available?
dequeue-transaction
transaction?
transaction-context
transaction-value)
(struct transaction-manager (queue) #:transparent)
(struct transaction (context
[value* #:mutable]
[ready? #:mutable]))
(define (make-transaction-manager)
(transaction-manager (make-queue)))
(define (open-transaction manager context)
(define txn (transaction context #f #f))
(values txn (transaction-manager (enqueue (transaction-manager-queue manager) txn))))
(define (close-transaction! txn value)
(when (transaction-ready? txn)
(error 'close-transaction! "Attempt to close previously-closed transaction"))
(set-transaction-value*! txn value)
(set-transaction-ready?! txn #t)
value)
(define (transaction-available? manager)
(if (queue-empty? (transaction-manager-queue manager))
#f
(let-values (((txn rest) (dequeue (transaction-manager-queue manager))))
(transaction-ready? txn))))
(define (dequeue-transaction manager)
(let-values (((txn rest) (dequeue (transaction-manager-queue manager))))
(values txn (transaction-manager rest))))
(define (transaction-value txn)
(when (not (transaction-ready? txn))
(error 'transaction-value "Attempt to extract value from unclosed transaction"))
(transaction-value* txn))