]> gitweb.factorcode.org Git - factor.git/commitdiff
Disposables are now registered in a global disposables set. To take advantage of...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 24 Aug 2009 07:26:13 +0000 (02:26 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 24 Aug 2009 07:26:13 +0000 (02:26 -0500)
29 files changed:
basis/alien/destructors/destructors.factor
basis/bootstrap/tools/tools.factor
basis/cache/cache.factor
basis/concurrency/mailboxes/mailboxes.factor
basis/core-foundation/fsevents/fsevents.factor
basis/core-text/core-text.factor
basis/help/handbook/handbook.factor
basis/io/backend/unix/unix.factor
basis/io/backend/windows/windows.factor
basis/io/mmap/mmap.factor
basis/io/monitors/linux/linux.factor
basis/io/monitors/monitors.factor
basis/io/monitors/recursive/recursive.factor
basis/io/ports/ports.factor
basis/io/sockets/secure/openssl/openssl.factor
basis/io/sockets/secure/secure.factor
basis/io/sockets/sockets-tests.factor
basis/opengl/textures/textures.factor
basis/pango/layouts/layouts.factor
basis/tools/deploy/shaker/shaker.factor
basis/tools/deploy/shaker/strip-destructors.factor [new file with mode: 0644]
basis/tools/destructors/authors.txt [new file with mode: 0644]
basis/tools/destructors/destructors-docs.factor [new file with mode: 0644]
basis/tools/destructors/destructors.factor [new file with mode: 0644]
basis/windows/com/wrapper/wrapper.factor
basis/windows/uniscribe/uniscribe.factor
core/destructors/destructors-docs.factor
core/destructors/destructors.factor
core/io/streams/c/c.factor

index 374d6425c44208a6f814709aeaf5f4d859c10388..24a75304b751c5a54e3bd22faf3aef0d4bf18f6f 100755 (executable)
@@ -16,9 +16,10 @@ N [ F stack-effect out>> length ]
 
 WHERE
 
-TUPLE: F-destructor alien disposed ;
+TUPLE: F-destructor < disposable alien ;
 
-: <F-destructor> ( alien -- destructor ) f F-destructor boa ; inline
+: <F-destructor> ( alien -- destructor )
+    F-destructor new-disposable swap >>alien ; inline
 
 M: F-destructor dispose* alien>> F N ndrop ;
 
index e5e7e869c87bcca3c5c063f623db4673799365cb..6bdfd6241c0b619925e6d420f0e38af00d28bf47 100644 (file)
@@ -8,6 +8,7 @@ IN: bootstrap.tools
     "tools.crossref"
     "tools.errors"
     "tools.deploy"
+    "tools.destructors"
     "tools.disassembler"
     "tools.memory"
     "tools.profiler"
index 3dab1acac8c8f865e5211494e2ab0978e01ad6c7..a226500c63db8aa291fe67d8b0a87ea8d8ead028 100644 (file)
@@ -3,10 +3,10 @@
 USING: kernel assocs math accessors destructors fry sequences ;
 IN: cache
 
-TUPLE: cache-assoc assoc max-age disposed ;
+TUPLE: cache-assoc < disposable assoc max-age ;
 
 : <cache-assoc> ( -- cache )
-    H{ } clone 10 f cache-assoc boa ;
+    cache-assoc new-disposable H{ } clone >>assoc 10 >>max-age ;
 
 <PRIVATE
 
index 419277647d778d7679ff74f765ae59de6b2af94f..7834a2a3e1b4f1be0100645b55260e246b0d2b2c 100755 (executable)
@@ -6,12 +6,12 @@ arrays assocs init system concurrency.conditions accessors
 debugger debugger.threads locals fry ;\r
 IN: concurrency.mailboxes\r
 \r
-TUPLE: mailbox threads data disposed ;\r
+TUPLE: mailbox < disposable threads data ;\r
 \r
 M: mailbox dispose* threads>> notify-all ;\r
 \r
 : <mailbox> ( -- mailbox )\r
-    <dlist> <dlist> f mailbox boa ;\r
+    mailbox new-disposable <dlist> >>threads <dlist> >>data ;\r
 \r
 : mailbox-empty? ( mailbox -- bool )\r
     data>> deque-empty? ;\r
index 1956cd9c20d4d6761d978fa8afa4ff765652a3f0..4aa531f1825e01f9081946d7b9daaf7cf0649389 100644 (file)
@@ -181,15 +181,15 @@ SYMBOL: event-stream-callbacks
     }
     "cdecl" [ (master-event-source-callback) ] alien-callback ;
 
-TUPLE: event-stream info handle disposed ;
+TUPLE: event-stream < disposable info handle ;
 
 : <event-stream> ( quot paths latency flags -- event-stream )
     [
-        add-event-source-callback dup
-        [ master-event-source-callback ] dip
+        add-event-source-callback
+        [ master-event-source-callback ] keep
     ] 3dip <FSEventStream>
     dup enable-event-stream
-    f event-stream boa ;
+    event-stream new-disposable swap >>handle swap >>info ;
 
 M: event-stream dispose*
     {
index de3b5ac715caecf4d238ffcd913ed08407624d97..4add71b08fdd4cb7b9b86e789c1f6f675084e4e7 100644 (file)
@@ -46,7 +46,7 @@ ERROR: not-a-string object ;
         CTLineCreateWithAttributedString
     ] with-destructors ;
 
-TUPLE: line line metrics image loc dim disposed ;
+TUPLE: line < disposable line metrics image loc dim ;
 
 : typographic-bounds ( line -- width ascent descent leading )
     0 <CGFloat> 0 <CGFloat> 0 <CGFloat>
@@ -109,6 +109,8 @@ TUPLE: line line metrics image loc dim disposed ;
 
 :: <line> ( font string -- line )
     [
+        line new-disposable
+
         [let* | open-font [ font cache-font ]
                 line [ string open-font font foreground>> <CTLine> |CFRelease ]
 
@@ -120,7 +122,11 @@ TUPLE: line line metrics image loc dim disposed ;
                 ext [ (loc) (dim) [ + ceiling ] 2map ]
                 dim [ ext loc [ - >integer ] 2map ]
                 metrics [ open-font line compute-line-metrics ] |
-            line metrics
+
+            line >>line
+
+            metrics >>metrics
+
             dim [
                 {
                     [ font dim fill-background ]
@@ -128,11 +134,12 @@ TUPLE: line line metrics image loc dim disposed ;
                     [ loc set-text-position ]
                     [ [ line ] dip CTLineDraw ]
                 } cleave
-            ] make-bitmap-image
-            metrics loc dim line-loc
-            metrics metrics>dim
+            ] make-bitmap-image >>image
+
+            metrics loc dim line-loc >>loc
+
+            metrics metrics>dim >>dim
         ]
-        f line boa
     ] with-destructors ;
 
 M: line dispose* line>> CFRelease ;
index 1c633600255fcc9975006396dc975395db082575..5db362d9bc3e328a8391b2dd7710ebe06b00f683 100644 (file)
@@ -287,9 +287,9 @@ ARTICLE: "handbook-tools-reference" "Developer tools"
 { $heading "Debugging" }
 { $subsection "prettyprint" }
 { $subsection "inspector" }
+{ $subsection "tools.inference" }
 { $subsection "tools.annotations" }
 { $subsection "tools.deprecation" }
-{ $subsection "tools.inference" }
 { $heading "Browsing" }
 { $subsection "see" }
 { $subsection "tools.crossref" }
@@ -299,6 +299,7 @@ ARTICLE: "handbook-tools-reference" "Developer tools"
 { $subsection "profiling" }
 { $subsection "tools.memory" }
 { $subsection "tools.threads" }
+{ $subsection "tools.destructors" }
 { $subsection "tools.disassembler" }
 { $heading "Deployment" }
 { $subsection "tools.deploy" } ;
index 1a52ce6f345df6486f87ca11771cb3b520c66b72..4b7ef4b40f70afdb02600143abaca52ab3aec125 100644 (file)
@@ -4,14 +4,15 @@ USING: alien alien.c-types alien.syntax generic assocs kernel
 kernel.private math io.ports sequences strings sbufs threads
 unix vectors io.buffers io.backend io.encodings math.parser
 continuations system libc namespaces make io.timeouts
-io.encodings.utf8 destructors accessors summary combinators
-locals unix.time fry io.backend.unix.multiplexers ;
+io.encodings.utf8 destructors destructors.private accessors
+summary combinators locals unix.time fry
+io.backend.unix.multiplexers ;
 QUALIFIED: io
 IN: io.backend.unix
 
 GENERIC: handle-fd ( handle -- fd )
 
-TUPLE: fd fd disposed ;
+TUPLE: fd < disposable fd ;
 
 : init-fd ( fd -- fd )
     [
@@ -25,14 +26,16 @@ TUPLE: fd fd disposed ;
     #! since on OS X 10.3, this operation fails from init-io
     #! when running the Factor.app (presumably because fd 0 and
     #! 1 are closed).
-    f fd boa ;
+    fd new-disposable swap >>fd ;
 
 M: fd dispose
     dup disposed>> [ drop ] [
-        [ cancel-operation ]
-        [ t >>disposed drop ]
-        [ fd>> close-file ]
-        tri
+        {
+            [ cancel-operation ]
+            [ t >>disposed drop ]
+            [ unregister-disposable ]
+            [ fd>> close-file ]
+        } cleave
     ] if ;
 
 M: fd handle-fd dup check-disposed fd>> ;
@@ -133,7 +136,7 @@ M: unix io-multiplex ( ms/f -- )
 ! pipe to non-blocking, and read from it instead of the real
 ! stdin. Very crufty, but it will suffice until we get native
 ! threading support at the language level.
-TUPLE: stdin control size data disposed ;
+TUPLE: stdin < disposable control size data ;
 
 M: stdin dispose*
     [
@@ -168,7 +171,7 @@ M: stdin refill
 : data-read-fd ( -- fd ) &: stdin_read *uint ;
 
 : <stdin> ( -- stdin )
-    stdin new
+    stdin new-disposable
         control-write-fd <fd> <output-port> >>control
         size-read-fd <fd> init-fd <input-port> >>size
         data-read-fd <fd> >>data ;
index fde5cf9b12bd12131c1df5ca99e868226dc50b3c..5922e217b0ef299e9f7b536906db9a79e7fbf219 100755 (executable)
@@ -7,33 +7,21 @@ windows.kernel32 windows.shell32 windows.types windows.winsock
 splitting continuations math.bitwise accessors init sets assocs ;
 IN: io.backend.windows
 
-: win32-handles ( -- assoc )
-    \ win32-handles [ H{ } clone ] initialize-alien ;
-
-TUPLE: win32-handle < identity-tuple handle disposed ;
-
-M: win32-handle hashcode* handle>> hashcode* ;
+TUPLE: win32-handle < disposable handle ;
 
 : set-inherit ( handle ? -- )
     [ handle>> HANDLE_FLAG_INHERIT ] dip
     >BOOLEAN SetHandleInformation win32-error=0/f ;
 
 : new-win32-handle ( handle class -- win32-handle )
-    new swap >>handle
-    dup f set-inherit
-    dup win32-handles conjoin ;
+    new-disposable swap >>handle
+    dup f set-inherit ;
 
 : <win32-handle> ( handle -- win32-handle )
     win32-handle new-win32-handle ;
 
-ERROR: disposing-twice ;
-
-: unregister-handle ( handle -- )
-    win32-handles delete-at*
-    [ t >>disposed drop ] [ disposing-twice ] if ;
-
 M: win32-handle dispose* ( handle -- )
-    [ unregister-handle ] [ handle>> CloseHandle win32-error=0/f ] bi ;
+    handle>> CloseHandle win32-error=0/f ;
 
 TUPLE: win32-file < win32-handle ptr ;
 
@@ -54,7 +42,7 @@ HOOK: add-completion io-backend ( port -- )
     <win32-file> |dispose
     dup add-completion ;
 
-: share-mode ( -- fixnum )
+: share-mode ( -- n )
     {
         FILE_SHARE_READ
         FILE_SHARE_WRITE
index 9a4443e8e5a738c87dd0d0ff2f42a85feeca9ad8..aa3ac624a07b5893621c5f40622fca946bf8bb59 100644 (file)
@@ -6,30 +6,29 @@ accessors vocabs.loader combinators alien.c-types
 math ;
 IN: io.mmap
 
-TUPLE: mapped-file address handle length disposed ;
+TUPLE: mapped-file < disposable address handle length ;
 
 HOOK: (mapped-file-reader) os ( path length -- address handle )
 HOOK: (mapped-file-r/w) os ( path length -- address handle )
 
-ERROR: bad-mmap-size path size ;
+ERROR: bad-mmap-size n ;
 
 <PRIVATE
 
-: prepare-mapped-file ( path -- path' n )
-    [ normalize-path ] [ file-info size>> ] bi
-    dup 0 <= [ bad-mmap-size ] when ;
+: prepare-mapped-file ( path quot -- mapped-file path' length )
+    [
+        [ normalize-path ] [ file-info size>> ] bi
+        [ dup 0 <= [ bad-mmap-size ] [ 2drop ] if ]
+        [ nip mapped-file new-disposable swap >>length ]
+    ] dip 2tri [ >>address ] [ >>handle ] bi* ; inline
 
 PRIVATE>
 
 : <mapped-file-reader> ( path -- mmap )
-    prepare-mapped-file
-    [ (mapped-file-reader) ] keep
-    f mapped-file boa ;
+    [ (mapped-file-reader) ] prepare-mapped-file ;
 
 : <mapped-file> ( path -- mmap )
-    prepare-mapped-file
-    [ (mapped-file-r/w) ] keep
-    f mapped-file boa ;
+    [ (mapped-file-r/w) ] prepare-mapped-file ;
 
 HOOK: close-mapped-file io-backend ( mmap -- )
 
index 9097e7e864fe2cc923f332c894b13b2b941e2136..9b3688d0232cca184069b2a4377515af5cbbf2bf 100644 (file)
@@ -12,7 +12,7 @@ SYMBOL: watches
 
 SYMBOL: inotify
 
-TUPLE: linux-monitor < monitor wd inotify watches disposed ;
+TUPLE: linux-monitor < monitor wd inotify watches ;
 
 : <linux-monitor> ( wd path mailbox -- monitor )
     linux-monitor new-monitor
index cc8cea37d21a5838e338c027a0be3e7b6f02cbdc..d8bb1ed48824955c21beea933ce1e35a8e984cd7 100644 (file)
@@ -20,7 +20,7 @@ M: object dispose-monitors ;
         [ dispose-monitors ] [ ] cleanup
     ] with-scope ; inline
 
-TUPLE: monitor < identity-tuple path queue timeout ;
+TUPLE: monitor < disposable path queue timeout ;
 
 M: monitor hashcode* path>> hashcode* ;
 
@@ -29,7 +29,7 @@ M: monitor timeout timeout>> ;
 M: monitor set-timeout (>>timeout) ;
 
 : new-monitor ( path mailbox class -- monitor )
-    new
+    new-disposable
         swap >>queue
         swap >>path ; inline
 
index 943345bf1831e1ff5edc134c7413b1fe589e4f35..75dfd234a8ce77ac4decf28f2049382037867227 100644 (file)
@@ -8,7 +8,7 @@ IN: io.monitors.recursive
 
 ! Simulate recursive monitors on platforms that don't have them
 
-TUPLE: recursive-monitor < monitor children thread ready disposed ;
+TUPLE: recursive-monitor < monitor children thread ready ;
 
 : notify? ( -- ? ) monitor tget ready>> promise-fulfilled? ;
 
index b2d71fd53514ffa07bbd6761dde6941f80db5a6d..49f6166e0068debd52c80c3985e5fab999a2fabc 100644 (file)
@@ -10,14 +10,14 @@ IN: io.ports
 SYMBOL: default-buffer-size
 64 1024 * default-buffer-size set-global
 
-TUPLE: port handle timeout disposed ;
+TUPLE: port < disposable handle timeout ;
 
 M: port timeout timeout>> ;
 
 M: port set-timeout (>>timeout) ;
 
 : <port> ( handle class -- port )
-    new swap >>handle ; inline
+    new-disposable swap >>handle ; inline
 
 TUPLE: buffered-port < port { buffer buffer } ;
 
index 07246354e3e98871ecb01acd14ecd76cc52240a9..8f596da0bdca579582964e900e62c62b59fff276 100644 (file)
@@ -78,9 +78,9 @@ TUPLE: openssl-context < secure-context aliens sessions ;
         SSL_CTX_set_verify_depth
     ] [ drop ] if ;
 
-TUPLE: bio handle disposed ;
+TUPLE: bio < disposable handle ;
 
-: <bio> ( handle -- bio ) f bio boa ;
+: <bio> ( handle -- bio ) bio new-disposable swap >>handle ;
 
 M: bio dispose* handle>> BIO_free ssl-error ;
 
@@ -94,9 +94,9 @@ M: bio dispose* handle>> BIO_free ssl-error ;
         SSL_CTX_set_tmp_dh ssl-error
     ] [ drop ] if ;
 
-TUPLE: rsa handle disposed ;
+TUPLE: rsa < disposable handle ;
 
-: <rsa> ( handle -- rsa ) f rsa boa ;
+: <rsa> ( handle -- rsa ) rsa new-disposable swap >>handle ;
 
 M: rsa dispose* handle>> RSA_free ;
 
@@ -109,7 +109,7 @@ M: rsa dispose* handle>> RSA_free ;
     SSL_CTX_set_tmp_rsa ssl-error ;
 
 : <openssl-context> ( config ctx -- context )
-    openssl-context new
+    openssl-context new-disposable
         swap >>handle
         swap >>config
         V{ } clone >>aliens
@@ -139,7 +139,7 @@ M: openssl-context dispose*
     [ handle>> SSL_CTX_free ]
     tri ;
 
-TUPLE: ssl-handle file handle connected disposed ;
+TUPLE: ssl-handle < disposable file handle connected ;
 
 SYMBOL: default-secure-context
 
@@ -151,8 +151,10 @@ SYMBOL: default-secure-context
     ] unless* ;
 
 : <ssl-handle> ( fd -- ssl )
-    current-secure-context handle>> SSL_new dup ssl-error
-    f f ssl-handle boa ;
+    ssl-handle new-disposable
+    current-secure-context handle>> SSL_new
+    dup ssl-error >>handle
+    swap >>file ;
 
 M: ssl-handle dispose*
     [ handle>> SSL_free ] [ file>> dispose ] bi ;
index bff2dbaf1a22d4e3765ef3f7760200efb6fd749e..e654caf0b8a83ef561f8f641462719314b3fc16b 100644 (file)
@@ -29,7 +29,7 @@ ephemeral-key-bits ;
         "vocab:openssl/cacert.pem" >>ca-file
         t >>verify ;
 
-TUPLE: secure-context config handle disposed ;
+TUPLE: secure-context < disposable config handle ;
 
 HOOK: <secure-context> secure-socket-backend ( config -- context )
 
index dc0c698699b8d68b940cf4296018d20c38fdd08f..a4a3f0702baecdf647eb36f9f3e4b5f04b9dfd4c 100644 (file)
@@ -79,6 +79,8 @@ concurrency.promises threads io.streams.string ;
 ! See what happens if other end is closed
 [ ] [ <promise> "port" set ] unit-test
 
+[ ] [ "datagram3" get dispose ] unit-test
+
 [ ] [
     [
         "127.0.0.1" 0 <inet4> utf8 <server>
@@ -93,6 +95,8 @@ concurrency.promises threads io.streams.string ;
 
 [ "hello" f ] [
     "port" get ?promise utf8 [
+        1 seconds input-stream get set-timeout
+        1 seconds output-stream get set-timeout
         "hi\n" write flush readln readln
     ] with-client
 ] unit-test
index 34cb14a442f756fc2c125c44b5eb57d1851a1a11..528aaaa12f67a8e10dcc6f64f19421cdd522f6fb 100755 (executable)
@@ -268,7 +268,7 @@ DEFER: make-texture
 
 <PRIVATE
 
-TUPLE: single-texture image dim loc texture-coords texture display-list disposed ;
+TUPLE: single-texture < disposable image dim loc texture-coords texture display-list ;
 
 : adjust-texture-dim ( dim -- dim' )
     non-power-of-2-textures? get [
@@ -331,7 +331,7 @@ TUPLE: single-texture image dim loc texture-coords texture display-list disposed
     GL_COMPILE [ [ dim>> ] keep draw-textured-rect ] make-dlist ;
 
 : <single-texture> ( image loc -- texture )
-    single-texture new swap >>loc swap [ >>image ] [ dim>> >>dim ] bi
+    single-texture new-disposable swap >>loc swap [ >>image ] [ dim>> >>dim ] bi
     dup image>> dim>> product 0 = [
         dup texture-coords >>texture-coords
         dup image>> make-texture >>texture
@@ -347,7 +347,7 @@ M: single-texture draw-scaled-texture
         dup texture>> [ draw-textured-rect ] [ 2drop ] if
     ] if ;
 
-TUPLE: multi-texture grid display-list loc disposed ;
+TUPLE: multi-texture < disposable grid display-list loc ;
 
 : image-locs ( image-grid -- loc-grid )
     [ first [ dim>> first ] map ] [ [ first dim>> second ] map ] bi
@@ -373,11 +373,9 @@ TUPLE: multi-texture grid display-list loc disposed ;
 
 : <multi-texture> ( image-grid loc -- multi-texture )
     [
-        [
-            <texture-grid> dup
-            make-textured-grid-display-list
-        ] keep
-        f multi-texture boa
+        [ multi-texture new-disposable ] 2dip
+        [ nip >>loc ] [ <texture-grid> >>grid ] 2bi
+        dup grid>> make-textured-grid-display-list >>display-list
     ] with-destructors ;
 
 M: multi-texture draw-scaled-texture nip draw-texture ;
index 25aee74ca49cf76f071aead5f7da9d1248f7a078..88c6f17093e62c67d9d8265fab184e3d93061e43 100644 (file)
@@ -60,7 +60,7 @@ pango_layout_iter_free ( PangoLayoutIter* iter ) ;
 
 DESTRUCTOR: pango_layout_iter_free
 
-TUPLE: layout font string selection layout metrics ink-rect logical-rect image disposed ;
+TUPLE: layout < disposable font string selection layout metrics ink-rect logical-rect image ;
 
 SYMBOL: dpi
 
@@ -186,7 +186,7 @@ MEMO: missing-font-metrics ( font -- metrics )
 
 : <layout> ( font string -- line )
     [
-        layout new
+        layout new-disposable
             swap unpack-selection
             swap >>font
             dup [ string>> ] [ font>> ] bi <PangoLayout> >>layout
index c6b67313214ac2214e3e43ac33a21b9caadb64cd..c587f842ca268d26429e88407af78cd8f86d8fd7 100755 (executable)
@@ -24,11 +24,12 @@ IN: tools.deploy.shaker
 : strip-init-hooks ( -- )
     "Stripping startup hooks" show
     {
+        "alien.strings"
         "command-line"
         "cpu.x86"
+        "destructors"
         "environment"
         "libc"
-        "alien.strings"
     }
     [ init-hooks get delete-at ] each
     deploy-threads? get [
@@ -65,6 +66,13 @@ IN: tools.deploy.shaker
         run-file
     ] when ;
 
+: strip-destructors ( -- )
+    "libc" vocab [
+        "Stripping destructor debug code" show
+        "vocab:tools/deploy/shaker/strip-destructors.factor"
+        run-file
+    ] when ;
+
 : strip-call ( -- )
     "Stripping stack effect checking from call( and execute(" show
     "vocab:tools/deploy/shaker/strip-call.factor" run-file ;
@@ -278,6 +286,8 @@ IN: tools.deploy.shaker
 
         "mallocs" "libc.private" lookup ,
 
+        "disposables" "destructors" lookup ,
+
         deploy-threads? [
             "initial-thread" "threads" lookup ,
         ] unless
@@ -478,6 +488,7 @@ SYMBOL: deploy-vocab
 : strip ( -- )
     init-stripper
     strip-libc
+    strip-destructors
     strip-call
     strip-cocoa
     strip-debugger
diff --git a/basis/tools/deploy/shaker/strip-destructors.factor b/basis/tools/deploy/shaker/strip-destructors.factor
new file mode 100644 (file)
index 0000000..86c08eb
--- /dev/null
@@ -0,0 +1,6 @@
+USE: kernel
+IN: destructors.private
+
+: register-disposable ( obj -- ) drop ; inline
+
+: unregister-disposable ( obj -- ) drop ; inline
diff --git a/basis/tools/destructors/authors.txt b/basis/tools/destructors/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/tools/destructors/destructors-docs.factor b/basis/tools/destructors/destructors-docs.factor
new file mode 100644 (file)
index 0000000..e5a8f03
--- /dev/null
@@ -0,0 +1,21 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax quotations ;
+IN: tools.destructors
+
+HELP: disposables.
+{ $description "Print the number of disposable objects of each class." } ;
+
+HELP: leaks
+{ $values
+    { "quot" quotation }
+}
+{ $description "Runs a quotation, printing any increases in the number of disposable objects after the quotation returns." } ;
+
+ARTICLE: "tools.destructors" "Destructor tools"
+"The " { $vocab-link "tools.destructors" } " vocabulary provides words for tracking down resource leaks."
+{ $subsection disposables. }
+{ $subsection leaks }
+{ $see-also "destructors" } ;
+
+ABOUT: "tools.destructors"
diff --git a/basis/tools/destructors/destructors.factor b/basis/tools/destructors/destructors.factor
new file mode 100644 (file)
index 0000000..4f182c6
--- /dev/null
@@ -0,0 +1,31 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: assocs classes destructors fry kernel math namespaces
+prettyprint sequences sets sorting ;
+IN: tools.destructors
+
+<PRIVATE
+
+: disposable-tally ( -- assoc )
+    disposables get
+    H{ } clone [ [ keys ] dip '[ class _ inc-at ] each ] keep ;
+
+: subtract-values ( assoc1 assoc2 -- assoc )
+    [ [ keys ] bi@ append prune ] 2keep
+    H{ } clone [
+        '[
+            [ _ _ [ at 0 or ] bi-curry@ bi - ] keep _ set-at
+        ] each
+    ] keep ;
+
+: (disposables.) ( assoc -- )
+    >alist sort-keys simple-table. ;
+
+PRIVATE>
+
+: disposables. ( -- )
+    disposable-tally (disposables.) ;
+
+: leaks ( quot -- )
+    disposable-tally [ call disposable-tally ] dip subtract-values
+    (disposables.) ; inline
index beac4b6c27397c5a13b13c634946dd8a0a57f839..81ae923d26e1a0c562133d592288cc9f3a519ed3 100755 (executable)
@@ -6,7 +6,7 @@ destructors fry math.parser generalizations sets
 specialized-arrays.alien specialized-arrays.direct.alien ;
 IN: windows.com.wrapper
 
-TUPLE: com-wrapper callbacks vtbls disposed ;
+TUPLE: com-wrapper < disposable callbacks vtbls ;
 
 <PRIVATE
 
@@ -153,7 +153,7 @@ PRIVATE>
     [ +live-wrappers+ get adjoin ] bi ;
 
 : <com-wrapper> ( implementations -- wrapper )
-    (make-callbacks) f f com-wrapper boa
+    com-wrapper new-disposable swap (make-callbacks) >>vtbls
     dup allocate-wrapper ;
 
 M: com-wrapper dispose*
index 7c5c26c2da82733a2be5afc9cc7232ebe5a5f999..457f4bc9f017e59e3301d976f16c2376fc2457b2 100755 (executable)
@@ -7,7 +7,7 @@ windows.offscreen windows.gdi32 windows.ole32 windows.types
 windows.fonts opengl.textures locals windows.errors ;
 IN: windows.uniscribe
 
-TUPLE: script-string font string metrics ssa size image disposed ;
+TUPLE: script-string < disposable font string metrics ssa size image ;
 
 : line-offset>x ( n script-string -- x )
     2dup string>> length = [
@@ -89,7 +89,7 @@ TUPLE: script-string font string metrics ssa size image disposed ;
     TEXTMETRIC>metrics ;
 
 : <script-string> ( font string -- script-string )
-    [ script-string new ] 2dip
+    [ script-string new-disposable ] 2dip
         [ >>font ] [ >>string ] bi*
     [
         {
index ed7d4330264c1fb101fab1e793f1ecebad22b7f7..8a0c36b99aa2689a7ba6fdd037a706f94608db3e 100644 (file)
@@ -8,8 +8,8 @@ HELP: dispose
 $nl
 "No further operations can be performed on a disposable object after this call."
 $nl
-"Disposing an object which has already been disposed should have no effect, and in particular it should not fail with an error. To help implement this pattern, add a " { $slot "disposed" } " slot to your object and implement the " { $link dispose* } " method instead." }
-{ $notes "You must close disposable objects after you are finished working with them, to avoid leaking operating system resources. A convenient way to automate this is by using the " { $link with-disposal } " word."
+"Disposing an object which has already been disposed should have no effect, and in particular it should not fail with an error. To help implement this pattern, inherit from the " { $link disposable } " class and implement the " { $link dispose* } " method instead." }
+{ $notes "You must dispose of disposable objects after you are finished working with them, to avoid leaking operating system resources. A convenient way to automate this is by using the " { $link with-disposal } " word."
 $nl
 "The default implementation assumes the object has a " { $snippet "disposed" } " slot. If the slot is set to " { $link f } ", it calls " { $link dispose* } " and sets the slot to " { $link t } "." } ;
 
@@ -51,6 +51,9 @@ HELP: dispose-each
      { "seq" sequence } }
 { $description "Attempts to dispose of each element of a sequence and collects all of the errors into a sequence. If any errors are thrown during disposal, the last error is rethrown after all objects have been disposed." } ;
 
+HELP: disposables
+{ $var-description "Global variable holding all disposable objects which have not been disposed of yet. The " { $link new-disposable } " word adds objects here, and the " { $link dispose } " method on disposables removes them. The " { $link "tools.destructors" } " vocabulary provides some words for working with this data." } ;
+
 ARTICLE: "destructors-anti-patterns" "Resource disposal anti-patterns"
 "Words which create objects corresponding to external resources should always be used with " { $link with-disposal } ". The following code is wrong:"
 { $code
@@ -58,12 +61,9 @@ ARTICLE: "destructors-anti-patterns" "Resource disposal anti-patterns"
 }
 "The reason being that if " { $snippet "do stuff" } " throws an error, the resource will not be disposed of. The most important case where this can occur is with I/O streams, and the correct solution is to always use " { $link with-input-stream } " and " { $link with-output-stream } "; see " { $link "stdio" } " for details." ;
 
-ARTICLE: "destructors" "Deterministic resource disposal"
-"Operating system resources such as streams, memory mapped files, and so on are not managed by Factor's garbage collector and must be released when you are done with them. Failing to release a resource can lead to reduced performance and instability."
-$nl
-"Disposable object protocol:"
+ARTICLE: "destructors-using" "Using destructors"
+"Disposing of an object:"
 { $subsection dispose }
-{ $subsection dispose* }
 "Utility word for scoped disposal:"
 { $subsection with-disposal }
 "Utility word for disposing multiple objects:"
@@ -71,7 +71,23 @@ $nl
 "Utility words for more complex disposal patterns:"
 { $subsection with-destructors }
 { $subsection &dispose }
-{ $subsection |dispose }
-{ $subsection "destructors-anti-patterns" } ;
+{ $subsection |dispose } ;
+
+ARTICLE: "destructors-extending" "Writing new destructors"
+"Superclass for disposable objects:"
+{ $subsection disposable }
+"Parametrized constructor for disposable objects:"
+{ $subsection new-disposable }
+"Generic disposal word:"
+{ $subsection dispose* }
+"Global set of disposable objects:"
+{ $subsection disposables } ;
+
+ARTICLE: "destructors" "Deterministic resource disposal"
+"Operating system resources such as streams, memory mapped files, and so on are not managed by Factor's garbage collector and must be released when you are done with them. Failing to release a resource can lead to reduced performance and instability."
+{ $subsection "destructors-using" }
+{ $subsection "destructors-extending" }
+{ $subsection "destructors-anti-patterns" }
+{ $see-also "tools.destructors" } ;
 
 ABOUT: "destructors"
index 9a470d53c141f93d3761753965afb7452cee922b..39f0e9f2b9652871a945ebcfdad3dc6ed82c02ed 100644 (file)
@@ -1,10 +1,30 @@
-! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov.
+! Copyright (C) 2007, 2009 Doug Coleman, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors continuations kernel namespaces make
-sequences vectors ;
+sequences vectors sets assocs init ;
 IN: destructors
 
-TUPLE: disposable disposed ;
+SYMBOL: disposables
+
+[ H{ } clone disposables set-global ] "destructors" add-init-hook
+
+<PRIVATE
+
+: register-disposable ( obj -- )
+    disposables get conjoin ;
+
+: unregister-disposable ( obj -- )
+    disposables get delete-at ;
+
+PRIVATE>
+
+TUPLE: disposable < identity-tuple disposed id ;
+
+M: disposable hashcode* nip id>> ;
+
+: new-disposable ( class -- disposable )
+    new \ disposable counter >>id
+    dup register-disposable ; inline
 
 GENERIC: dispose* ( disposable -- )
 
@@ -18,6 +38,9 @@ GENERIC: dispose ( disposable -- )
 M: object dispose
     dup disposed>> [ drop ] [ t >>disposed dispose* ] if ;
 
+M: disposable dispose
+    [ unregister-disposable ] [ call-next-method ] bi ;
+
 : dispose-each ( seq -- )
     [
         [ [ dispose ] curry [ , ] recover ] each
index 7a7ac5a97ccfc7e42b2c2a42a9e3cefebbc7cc2c..aebc709a9e79372626c0bd6207d3bbf1cee93cda 100755 (executable)
@@ -6,7 +6,10 @@ io.encodings.utf8 alien.strings continuations destructors byte-arrays
 accessors combinators ;
 IN: io.streams.c
 
-TUPLE: c-stream handle disposed ;
+TUPLE: c-stream < disposable handle ;
+
+: new-c-stream ( handle class -- c-stream )
+    new-disposable swap >>handle ; inline
 
 M: c-stream dispose* handle>> fclose ;
 
@@ -20,7 +23,7 @@ M: c-stream stream-seek
 
 TUPLE: c-writer < c-stream ;
 
-: <c-writer> ( handle -- stream ) f c-writer boa ;
+: <c-writer> ( handle -- stream ) c-writer new-c-stream ;
 
 M: c-writer stream-element-type drop +byte+ ;
 
@@ -32,7 +35,7 @@ M: c-writer stream-flush dup check-disposed handle>> fflush ;
 
 TUPLE: c-reader < c-stream ;
 
-: <c-reader> ( handle -- stream ) f c-reader boa ;
+: <c-reader> ( handle -- stream ) c-reader new-c-stream ;
 
 M: c-reader stream-element-type drop +byte+ ;