Wills and Executors
Wills and Executors
윌 실행기(will executor)는 값들의 모음과 그와 연관된 윌 프로시저(will procedure, 일명 finalizer)를 관리해요. 각 값의 윌 프로시저는 그 값이 (가비지 컬렉터에 의해) 약한 참조(Weak Boxes 문서 참고) 또는 다른 윌 실행기의 등록자(registrant)를 통해서만 도달 가능하다고 증명되면 실행될 준비가 돼요. 윌은 도달 불가능한 값에 연관된 데이터의 정리 동작을 트리거하는 데 유용해요. 예를 들어 객체가 더 이상 사용되지 않을 때 객체에 내장된 포트를 닫는 경우가 있죠.
will-execute 또는 will-try-execute 프로시저를 호출하면 지정된 윌 실행기에서 준비된 윌이 실행돼요. 윌 실행기는 또한 동기화 가능한 이벤트이므로, sync나 sync/timeout으로 윌 실행기에 준비된 윌이 있는지 감지할 수 있어요. 윌은 자동으로 실행되지 않는데, 특정 프로그램은 경쟁 조건(race condition)을 피하기 위해 제어가 필요하기 때문이에요. 하지만 프로그램은 특정 실행기의 윌을 실행하는 일만 하는 스레드를 만들 수 있어요.
값이 여러 윌(하나 또는 여러 실행기에)에 등록되면, 윌은 등록된 순서의 역순으로 준비돼요. 윌 프로시저를 준비하면 값이 다시 도달 가능해지므로, 윌을 실행하고 그 값이 다시 오직 약한 참조를 통해서만 도달 불가능하다고 증명되기 전에는 다른 윌이 준비되거나 실행되지 않아요. 그러나 서로 다른 도달 불가능한 값에 대한 윌은, 그 값들이 서로에게서 도달 가능한지와 무관하게 동시에 준비돼요.
윌 실행기의 등록자는 해당 윌 프로시저가 실행될 때까지 비약하게(non-weakly) 유지돼요. 따라서 약한 박스(Weak Boxes 문서 참고)의 내용 값이 윌 실행기에 등록되면, 그 값에 대해 모든 윌이 실행되고 그 값이 다시 오직 약한 참조를 통해서만 도달 가능하다고 증명되기 전까지는 약한 박스의 내용이 #f로 바뀌지 않아요.
윌 실행기는 동기화 가능한 이벤트(Events 문서 참고)로 사용할 수 있어요. will-execute가 블록되지 않을 때 윌 실행기는 동기화 준비가 된 것이고, 윌 실행기의 동기화 결과는 윌 실행기 자신이에요.
다음 예시들은 동기화가 필요하지 않을 때 정리 동작을 실행하는 방법을 보여줘요. 등록된 실행기들이 준비되는 대로 다른 스레드에서 그냥 실행할 뿐이에요.
출처: Racket Reference
본문
> (void
(thread
(λ ()
(let loop ()
(will-execute an-executor)
(loop)))))
> (define (executor-proc v) (printf "a-box is now garbage\n"))
> (define a-box-to-track (box #f))
> (will-register an-executor a-box-to-track executor-proc)
> (collect-garbage)
> (set! a-box-to-track #f)
> (collect-garbage)
a-box is now garbage
(make-will-executor) → will-executor?
관리되는 값이 없는 새 윌 실행기를 돌려줘요.
(will-executor? v) → boolean?
v : any/c
v가 윌 실행기이면 #t, 그렇지 않으면 #f를 돌려줘요.
(will-register executor v proc) → void?
executor : will-executor?
v : any/c
proc : (any/c . -> . any)
값 v를 윌 실행기 executor의 윌 프로시저 proc에 등록해요. v가 도달 불가능하다고 증명되면, 프로시저 proc은 will-execute 또는 will-try-execute를 통해 v를 인자로 호출될 준비가 돼요. proc 인자는 윌 프로시저가 실행될 때까지 강하게(strongly) 참조돼요.
(will-execute executor) → any
executor : will-executor?
executor 실행기에 등록된 단일 "도달 불가능한" 값에 대한 윌 프로시저를 호출해요. 윌 프로시저가 돌려주는 값들은 will-execute 호출의 결과예요. 즉시 실행할 준비가 된 윌이 없으면 will-execute는 준비될 때까지 블록돼요.
(will-try-execute executor [v]) → any
executor : any/c
v : any/c = #f
즉시 실행할 준비가 된 윌이 있으면 will-execute와 같아요. 그렇지 않으면 v가 돌려져요.
base 패키지 6.90.0.4 버전에서 변경됨: v 인자가 추가되었어요.