#lang scheme/base
(require scheme/contract
(file "number.ss")
(file "profile-internal.ss"))
(define split-time-cell
(make-thread-cell #f))
(define (split-time-ref)
(thread-cell-ref split-time-cell))
(define (split-time-set! time)
(thread-cell-set! split-time-cell time))
(define *all-timers* null)
(define (create-timer name [value 0])
(define ans (make-timer name value))
(set! *all-timers* (append *all-timers* (list ans)))
ans)
(define-syntax define-timer
(syntax-rules ()
[(_ id) (define id (create-timer 'id))]
[(_ id val) (define id (create-timer 'id val))]))
(define (timer-inc! timer increment)
(set-timer-value! timer (+ (timer-value timer) increment)))
(define (timer-reset! timer)
(set-timer-value! timer 0))
(define (all-timers)
*all-timers*)
(define current-timer
(make-parameter (create-timer 'top)))
(define (profile timer fn . args)
(dynamic-wind
(lambda ()
(define then (split-time-ref))
(define now (current-inexact-milliseconds))
(when (and then (current-timer))
(timer-inc! (current-timer) (- now then)))
(split-time-set! now))
(lambda ()
(parameterize ([current-timer timer])
(apply fn args)))
(lambda ()
(define then (split-time-ref))
(define now (current-inexact-milliseconds))
(when then (timer-inc! timer (- now then)))
(split-time-set! now))))
(define-syntax with-timer
(syntax-rules ()
[(_ timer expr ...)
(profile timer (lambda () expr ...))]))
(provide (except-out (struct-out timer) make-timer)
with-timer
define-timer)
(provide/contract
[rename create-timer make-timer (-> symbol? timer?)]
[timer-reset! (-> timer? void?)]
[all-timers (-> (listof timer?))]
[current-timer (-> timer?)]
[profile (->* (timer? procedure?) () #:rest any/c any)])