;;; Rate limiting -*- Scheme -*- ;;; Copyright (c) 2002 by Mike Sperber. (define-record-type rate-limiter :rate-limiter (really-make-rate-limiter simultaneous-requests access-lock block-lock current-requests) rate-limiter? (simultaneous-requests rate-limiter-simultaneous-requests) (access-lock rate-limiter-access-lock) (block-lock rate-limiter-block-lock) (current-requests rate-limiter-current-requests-unsafe set-rate-limiter-current-requests!)) (define (make-rate-limiter simultaneous-requests) (really-make-rate-limiter simultaneous-requests (make-lock) (make-lock) 0)) (define (rate-limit-block rate-limiter) (obtain-lock (rate-limiter-block-lock rate-limiter))) (define (rate-limit-open rate-limiter) (obtain-lock (rate-limiter-access-lock rate-limiter)) (let ((current-requests (+ 1 (rate-limiter-current-requests-unsafe rate-limiter)))) (set-rate-limiter-current-requests! rate-limiter current-requests) (if (>= current-requests (rate-limiter-simultaneous-requests rate-limiter)) (maybe-obtain-lock (rate-limiter-block-lock rate-limiter)) (release-lock (rate-limiter-block-lock rate-limiter)))) (release-lock (rate-limiter-access-lock rate-limiter))) (define (rate-limit-close rate-limiter) (obtain-lock (rate-limiter-access-lock rate-limiter)) (let ((current-requests (- (rate-limiter-current-requests-unsafe rate-limiter) 1))) (if (negative? current-requests) (error "rate-limiter: too many close operations" rate-limiter)) (set-rate-limiter-current-requests! rate-limiter current-requests) (if (= current-requests (- (rate-limiter-simultaneous-requests rate-limiter) 1)) ;; we just came back into range (release-lock (rate-limiter-block-lock rate-limiter)))) (release-lock (rate-limiter-access-lock rate-limiter))) (define (rate-limiter-current-requests rate-limiter) (obtain-lock (rate-limiter-access-lock rate-limiter)) (let ((current-requests (rate-limiter-current-requests-unsafe rate-limiter))) (release-lock (rate-limiter-access-lock rate-limiter)) current-requests))