destroy windows via finalization outside of the event loop

This commit is contained in:
Matthew Flatt 2010-10-29 07:02:34 -06:00
parent 9eabda614c
commit af6cad4913
8 changed files with 55 additions and 17 deletions

View File

@ -775,6 +775,11 @@
(super-tell #:type _void dealloc)))] (super-tell #:type _void dealloc)))]
[_ (error "oops")]) [_ (error "oops")])
'())] '())]
[(async ...)
(if (eq? (syntax-e id) 'dealloc)
;; so that objects can be destroyed in foreign threads:
#'(#:async-apply apply-directly)
#'())]
[in-cls (if in-class? [in-cls (if in-class?
#'(object-get-class cls) #'(object-get-class cls)
#'cls)] #'cls)]
@ -792,13 +797,16 @@
[super-tell do-super-tell]) [super-tell do-super-tell])
body0 body ... body0 body ...
dealloc-body ...))) dealloc-body ...)))
(_fun #:atomic? atomic? #:keep save-method! _id _id arg-type ... -> rt) (_fun #:atomic? atomic? #:keep save-method! async ...
_id _id arg-type ... -> rt)
(generate-layout rt (list arg-id ...)))))))))] (generate-layout rt (list arg-id ...)))))))))]
[else (raise-syntax-error #f [else (raise-syntax-error #f
"bad method form" "bad method form"
stx stx
#'m)]))])) #'m)]))]))
(define (apply-directly f) (f))
(define methods (make-hasheq)) (define methods (make-hasheq))
(define (save-method! m) (define (save-method! m)
;; Methods are never GCed, since classes are never unregistered ;; Methods are never GCed, since classes are never unregistered

View File

@ -31,10 +31,9 @@
(inherit get-cocoa) (inherit get-cocoa)
(super-new [parent parent] (super-new [parent parent]
[cocoa (let ([cocoa (values ; as-objc-allocation [cocoa (let ([cocoa (as-objc-allocation
;; We're leaving guages for now. There's some problem ;; Beware that a guage may be finally deallocated in
;; releasing gauges through a finalizer. My guess is that ;; a seperate OS-level thread
;; it has something to do with animation in a separate thread.
(tell (tell MyProgressIndicator alloc) init))]) (tell (tell MyProgressIndicator alloc) init))])
(tellv cocoa setIndeterminate: #:type _BOOL #f) (tellv cocoa setIndeterminate: #:type _BOOL #f)
(tellv cocoa setMaxValue: #:type _double* rng) (tellv cocoa setMaxValue: #:type _double* rng)

View File

@ -37,18 +37,12 @@
(define delete-me null) (define delete-me null)
(define (objc-delete o) (define (objc-delete o)
(atomically (tellv o release))
(set! delete-me (cons o delete-me))))
(define (clean-up-deleted) (define (clean-up-deleted)
;; called outside the event loop to actually delete objects (free-remembered-now objc-delete))
;; that might otherwise be in use during a callback
(for ([o (in-list (begin0
delete-me
(set! delete-me null)))])
(tellv o release)))
(define objc-allocator (allocator objc-delete)) (define objc-allocator (allocator remember-to-free-later))
(define-syntax-rule (as-objc-allocation expr) (define-syntax-rule (as-objc-allocation expr)
((objc-allocator (lambda () expr)))) ((objc-allocator (lambda () expr))))

View File

@ -1,8 +1,33 @@
#lang racket/base #lang racket/base
(require ffi/unsafe (require ffi/unsafe
ffi/unsafe/define ffi/unsafe/define
ffi/unsafe/atomic
"once.rkt") "once.rkt")
(provide (protect-out define-mz)) (provide (protect-out define-mz
remember-to-free-later
free-remembered-now))
(define-ffi-definer define-mz #f) (define-ffi-definer define-mz #f)
;; ----------------------------------------
(define to-free null)
;; Remember to free an object that might currently be in use during a
;; callback:
(define (remember-to-free-later o)
(start-atomic)
(set! to-free (cons o to-free))
(end-atomic))
;; Called outside the event loop to actually free objects that might
;; otherwise be in use during a callback:
(define (free-remembered-now free)
(start-atomic)
(for ([o (in-list (begin0
to-free
(set! to-free null)))])
(free o))
(end-atomic))

View File

@ -183,6 +183,7 @@
(define (dispatch-all-ready) (define (dispatch-all-ready)
(pre-event-sync #f) (pre-event-sync #f)
(clean-up-destroyed)
(when (gtk_events_pending) (when (gtk_events_pending)
(gtk_main_iteration_do #f) (gtk_main_iteration_do #f)
(dispatch-all-ready))) (dispatch-all-ready)))

View File

@ -24,6 +24,7 @@
as-gtk-allocation as-gtk-allocation
as-gtk-window-allocation as-gtk-window-allocation
clean-up-destroyed
g_free g_free
_gpath/free _gpath/free
@ -113,7 +114,10 @@
(define gtk-destroy ((deallocator) (lambda (v) (define gtk-destroy ((deallocator) (lambda (v)
(gtk_widget_destroy v) (gtk_widget_destroy v)
(g_object_unref v)))) (g_object_unref v))))
(define gtk-allocator (allocator gtk-destroy))
(define gtk-allocator (allocator remember-to-free-later))
(define (clean-up-destroyed)
(free-remembered-now gtk-destroy))
(define-syntax-rule (as-gtk-allocation expr) (define-syntax-rule (as-gtk-allocation expr)
((gtk-allocator (lambda () (let ([v expr]) ((gtk-allocator (lambda () (let ([v expr])

View File

@ -127,6 +127,7 @@
(define (dispatch-all-ready) (define (dispatch-all-ready)
;; in atomic mode ;; in atomic mode
(pre-event-sync #f) (pre-event-sync #f)
(clean-up-destroyed)
;; Windows uses messages above #x4000 to hilite items in the task bar, ;; Windows uses messages above #x4000 to hilite items in the task bar,
;; etc. In any case, these messages won't be handled by us, so they ;; etc. In any case, these messages won't be handled by us, so they

View File

@ -18,9 +18,12 @@
failed failed
GetLastError GetLastError
DestroyWindow DestroyWindow
NotifyWindowDestroy NotifyWindowDestroy
CreateWindowExW CreateWindowExW
clean-up-destroyed
GetWindowLongW GetWindowLongW
SetWindowLongW SetWindowLongW
SendMessageW SendMessageW/str SendMessageW SendMessageW/str
@ -73,6 +76,9 @@
#:wrap (deallocator)) #:wrap (deallocator))
(define NotifyWindowDestroy ((deallocator) void)) (define NotifyWindowDestroy ((deallocator) void))
(define (clean-up-destroyed)
(free-remembered-now DestroyWindow))
(define-user32 CreateWindowExW (_wfun _DWORD (define-user32 CreateWindowExW (_wfun _DWORD
_string/utf-16 _string/utf-16
_string/utf-16 _string/utf-16
@ -80,7 +86,7 @@
_int _int _int _int _int _int _int _int
_HWND _HMENU _HINSTANCE _pointer _HWND _HMENU _HINSTANCE _pointer
-> _HWND) -> _HWND)
#:wrap (allocator DestroyWindow)) #:wrap (allocator remember-to-free-later))
(define-user32 GetWindowLongW (_wfun _HWND _int -> _pointer)) (define-user32 GetWindowLongW (_wfun _HWND _int -> _pointer))
(define-user32 SetWindowLongW (_wfun _HWND _int _pointer -> _pointer)) (define-user32 SetWindowLongW (_wfun _HWND _int _pointer -> _pointer))