Fix conflict

db4
U-SLAVA-DFB8FF805\Slava 2008-05-15 01:44:23 -05:00
commit 667345e883
103 changed files with 635 additions and 728 deletions

View File

@ -1,7 +1,7 @@
IN: alien.c-types IN: alien.c-types
USING: alien help.syntax help.markup libc kernel.private USING: alien help.syntax help.markup libc kernel.private
byte-arrays math strings hashtables alien.syntax byte-arrays math strings hashtables alien.syntax
bit-arrays float-arrays debugger ; bit-arrays float-arrays debugger destructors ;
HELP: <c-type> HELP: <c-type>
{ $values { "type" hashtable } } { $values { "type" hashtable } }
@ -222,6 +222,9 @@ $nl
{ $subsection realloc } { $subsection realloc }
"You must always free pointers returned by any of the above words when the block of memory is no longer in use:" "You must always free pointers returned by any of the above words when the block of memory is no longer in use:"
{ $subsection free } { $subsection free }
"Utilities for automatically freeing memory in conjunction with " { $link with-destructors } ":"
{ $subsection &free }
{ $subsection |free }
"You can unsafely copy a range of bytes from one memory location to another:" "You can unsafely copy a range of bytes from one memory location to another:"
{ $subsection memcpy } { $subsection memcpy }
"You can copy a range of bytes from memory into a byte array:" "You can copy a range of bytes from memory into a byte array:"

View File

@ -2,7 +2,7 @@ USING: help.markup help.syntax kernel ;
IN: boxes IN: boxes
HELP: box HELP: box
{ $class-description "A data type holding a single value in the " { $link box-value } " slot. The " { $link box-full? } " slot indicates if the value is set." } ; { $class-description "A data type holding a single value in the " { $snippet "value" } " slot. The " { $snippet "occupied" } " slot indicates if the value is set." } ;
HELP: <box> HELP: <box>
{ $values { "box" box } } { $values { "box" box } }
@ -27,12 +27,11 @@ ARTICLE: "boxes" "Boxes"
{ $subsection box } { $subsection box }
"Creating an empty box:" "Creating an empty box:"
{ $subsection <box> } { $subsection <box> }
"Testing if a box is full:"
{ $subsection box-full? }
"Storing a value and removing a value from a box:" "Storing a value and removing a value from a box:"
{ $subsection >box } { $subsection >box }
{ $subsection box> } { $subsection box> }
"Safely removing a value:" "Safely removing a value:"
{ $subsection ?box } ; { $subsection ?box }
"Testing if a box is full can be done by reading the " { $snippet "occupied" } " slot." ;
ABOUT: "boxes" ABOUT: "boxes"

View File

@ -1,17 +1,17 @@
IN: boxes.tests IN: boxes.tests
USING: boxes namespaces tools.test ; USING: boxes namespaces tools.test accessors ;
[ ] [ <box> "b" set ] unit-test [ ] [ <box> "b" set ] unit-test
[ ] [ 3 "b" get >box ] unit-test [ ] [ 3 "b" get >box ] unit-test
[ t ] [ "b" get box-full? ] unit-test [ t ] [ "b" get occupied>> ] unit-test
[ 4 "b" >box ] must-fail [ 4 "b" >box ] must-fail
[ 3 ] [ "b" get box> ] unit-test [ 3 ] [ "b" get box> ] unit-test
[ f ] [ "b" get box-full? ] unit-test [ f ] [ "b" get occupied>> ] unit-test
[ "b" get box> ] must-fail [ "b" get box> ] must-fail
@ -21,4 +21,4 @@ USING: boxes namespaces tools.test ;
[ 12 t ] [ "b" get ?box ] unit-test [ 12 t ] [ "b" get ?box ] unit-test
[ f ] [ "b" get box-full? ] unit-test [ f ] [ "b" get occupied>> ] unit-test

View File

@ -1,24 +1,26 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel ; USING: kernel accessors ;
IN: boxes IN: boxes
TUPLE: box value full? ; TUPLE: box value occupied ;
: <box> ( -- box ) box new ; : <box> ( -- box ) box new ;
ERROR: box-full box ;
: >box ( value box -- ) : >box ( value box -- )
dup box-full? [ "Box already has a value" throw ] when dup occupied>>
t over set-box-full? [ box-full ] [ t >>occupied (>>value) ] if ;
set-box-value ;
ERROR: box-empty box ;
: box> ( box -- value ) : box> ( box -- value )
dup box-full? [ "Box empty" throw ] unless dup occupied>>
dup box-value f pick set-box-value [ [ f ] change-value f >>occupied drop ] [ box-empty ] if ;
f rot set-box-full? ;
: ?box ( box -- value/f ? ) : ?box ( box -- value/f ? )
dup box-full? [ box> t ] [ drop f f ] if ; dup occupied>> [ box> t ] [ drop f f ] if ;
: if-box? ( box quot -- ) : if-box? ( box quot -- )
>r ?box r> [ drop ] if ; inline >r ?box r> [ drop ] if ; inline

View File

@ -1,6 +1,6 @@
USING: help.markup help.syntax kernel kernel.private USING: help.markup help.syntax kernel kernel.private
continuations.private parser vectors arrays namespaces continuations.private parser vectors arrays namespaces
assocs words quotations io ; assocs words quotations ;
IN: continuations IN: continuations
ARTICLE: "errors-restartable" "Restartable errors" ARTICLE: "errors-restartable" "Restartable errors"
@ -28,13 +28,7 @@ $nl
{ $heading "Anti-pattern #3: Dropping and rethrowing" } { $heading "Anti-pattern #3: Dropping and rethrowing" }
"Do not use " { $link recover } " to handle an error by dropping it and throwing a new error. By losing the original error message, you signal to the user that something failed without leaving any indication of what actually went wrong. Either wrap the error in a new error containing additional information, or rethrow the original error. A more subtle form of this is using " { $link throw } " instead of " { $link rethrow } ". The " { $link throw } " word should only be used when throwing new errors, and never when rethrowing errors that have been caught." "Do not use " { $link recover } " to handle an error by dropping it and throwing a new error. By losing the original error message, you signal to the user that something failed without leaving any indication of what actually went wrong. Either wrap the error in a new error containing additional information, or rethrow the original error. A more subtle form of this is using " { $link throw } " instead of " { $link rethrow } ". The " { $link throw } " word should only be used when throwing new errors, and never when rethrowing errors that have been caught."
{ $heading "Anti-pattern #4: Logging and rethrowing" } { $heading "Anti-pattern #4: Logging and rethrowing" }
"If you are going to rethrow an error, do not log a message. If you do so, the user will see two log messages for the same error, which will clutter logs without adding any useful information." "If you are going to rethrow an error, do not log a message. If you do so, the user will see two log messages for the same error, which will clutter logs without adding any useful information." ;
{ $heading "Anti-pattern #5: Leaking external resources" }
"Words which create objects corresponding to external resources should always be used with " { $link with-disposal } ". The following code is wrong:"
{ $code
"<external-resource> ... do stuff ... dispose"
}
"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: "errors" "Error handling" ARTICLE: "errors" "Error handling"
"Support for handling exceptional situations such as bad user input, implementation bugs, and input/output errors is provided by a set of words built using continuations." "Support for handling exceptional situations such as bad user input, implementation bugs, and input/output errors is provided by a set of words built using continuations."
@ -88,19 +82,6 @@ $nl
ABOUT: "continuations" ABOUT: "continuations"
HELP: dispose
{ $values { "object" "a disposable object" } }
{ $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on."
$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." }
{ $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." } ;
HELP: with-disposal
{ $values { "object" "a disposable object" } { "quot" "a quotation with stack effect " { $snippet "( object -- )" } } }
{ $description "Calls the quotation, disposing the object with " { $link dispose } " after the quotation returns or if it throws an error." } ;
HELP: catchstack* HELP: catchstack*
{ $values { "catchstack" "a vector of continuations" } } { $values { "catchstack" "a vector of continuations" } }
{ $description "Outputs the current catchstack." } ; { $description "Outputs the current catchstack." } ;

View File

@ -101,23 +101,6 @@ SYMBOL: error-counter
[ 1 ] [ error-counter get ] unit-test [ 1 ] [ error-counter get ] unit-test
] with-scope ] with-scope
TUPLE: dispose-error ;
M: dispose-error dispose 3 throw ;
TUPLE: dispose-dummy disposed? ;
M: dispose-dummy dispose t >>disposed? drop ;
T{ dispose-error } "a" set
T{ dispose-dummy } "b" set
[ f ] [ "b" get disposed?>> ] unit-test
[ { "a" "b" } [ get ] map dispose-each ] [ 3 = ] must-fail-with
[ t ] [ "b" get disposed?>> ] unit-test
[ ] [ [ return ] with-return ] unit-test [ ] [ [ return ] with-return ] unit-test
[ { } [ ] attempt-all ] [ attempt-all-error? ] must-fail-with [ { } [ ] attempt-all ] [ attempt-all-error? ] must-fail-with

View File

@ -150,16 +150,6 @@ ERROR: attempt-all-error ;
] { } make peek swap [ rethrow ] when ] { } make peek swap [ rethrow ] when
] if ; inline ] if ; inline
GENERIC: dispose ( object -- )
: dispose-each ( seq -- )
[
[ [ dispose ] curry [ , ] recover ] each
] { } make dup empty? [ drop ] [ peek rethrow ] if ;
: with-disposal ( object quot -- )
over [ dispose ] curry [ ] cleanup ; inline
TUPLE: condition error restarts continuation ; TUPLE: condition error restarts continuation ;
C: <condition> condition ( error restarts cc -- condition ) C: <condition> condition ( error restarts cc -- condition )

View File

@ -0,0 +1,71 @@
USING: help.markup help.syntax libc kernel continuations io ;
IN: destructors
HELP: dispose
{ $values { "disposable" "a disposable object" } }
{ $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on."
$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 " { $snippet "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."
$nl
"The default implementation assumes the object has a " { $snippet "disposable" } " slot. If the slot is set to " { $link f } ", it calls " { $link dispose* } " and sets the slot to " { $link f } "." } ;
HELP: dispose*
{ $values { "disposable" "a disposable object" } }
{ $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on." }
{ $notes
"This word should not be called directly. It can be implemented on objects with a " { $snippet "disposable" } " slot to ensure that the object is only disposed once."
} ;
HELP: with-disposal
{ $values { "object" "a disposable object" } { "quot" "a quotation with stack effect " { $snippet "( object -- )" } } }
{ $description "Calls the quotation, disposing the object with " { $link dispose } " after the quotation returns or if it throws an error." } ;
HELP: with-destructors
{ $values { "quot" "a quotation" } }
{ $description "Calls a quotation within a new dynamic scope. This quotation may register destructors, on any object, by wrapping the object in a destructor and implementing " { $link dispose } " on that object type. After the quotation finishes, if an error was thrown, all destructors are called and the error is then rethrown. However, if the quotation was successful, only those destructors created with an 'always cleanup' flag will be destroyed." }
{ $notes
"Destructors generalize " { $link with-disposal } ". The following two lines are equivalent, except that the second line establishes a new dynamic scope:"
{ $code
"[ X ] with-disposal"
"[ &dispose X ] with-destructors"
}
}
{ $examples
{ $code "[ 10 malloc &free ] with-destructors" }
} ;
HELP: &dispose
{ $values { "disposable" "a disposable object" } }
{ $description "Marks the object for unconditional disposal at the end of the current " { $link with-destructors } " scope." } ;
HELP: |dispose
{ $values { "disposable" "a disposable object" } }
{ $description "Marks the object for disposal in the event of an error at the end of the current " { $link with-destructors } " scope." } ;
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
"<external-resource> ... do stuff ... dispose"
}
"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:"
{ $subsection dispose }
{ $subsection dispose* }
"Utility word for scoped disposal:"
{ $subsection with-disposal }
"Utility word for disposing multiple objects:"
{ $subsection dispose-each }
"Utility words for more complex disposal patterns:"
{ $subsection with-destructors }
{ $subsection &dispose }
{ $subsection |dispose }
{ $subsection "destructors-anti-patterns" } ;
ABOUT: "destructors"

View File

@ -1,6 +1,23 @@
USING: destructors kernel tools.test continuations ; USING: destructors kernel tools.test continuations ;
IN: destructors.tests IN: destructors.tests
TUPLE: dispose-error ;
M: dispose-error dispose 3 throw ;
TUPLE: dispose-dummy disposed? ;
M: dispose-dummy dispose t >>disposed? drop ;
T{ dispose-error } "a" set
T{ dispose-dummy } "b" set
[ f ] [ "b" get disposed?>> ] unit-test
[ { "a" "b" } [ get ] map dispose-each ] [ 3 = ] must-fail-with
[ t ] [ "b" get disposed?>> ] unit-test
TUPLE: dummy-obj destroyed? ; TUPLE: dummy-obj destroyed? ;
: <dummy-obj> dummy-obj new ; : <dummy-obj> dummy-obj new ;
@ -13,10 +30,10 @@ M: dummy-destructor dispose ( obj -- )
dummy-destructor-obj t swap set-dummy-obj-destroyed? ; dummy-destructor-obj t swap set-dummy-obj-destroyed? ;
: destroy-always : destroy-always
<dummy-destructor> add-always-destructor ; <dummy-destructor> &dispose drop ;
: destroy-later : destroy-later
<dummy-destructor> add-error-destructor ; <dummy-destructor> |dispose drop ;
[ t ] [ [ t ] [
[ [

View File

@ -0,0 +1,56 @@
! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors continuations kernel namespaces
sequences vectors ;
IN: destructors
TUPLE: disposable disposed ;
GENERIC: dispose* ( disposable -- )
ERROR: already-disposed disposable ;
: check-disposed ( disposable -- )
dup disposed>> [ already-disposed ] [ drop ] if ; inline
GENERIC: dispose ( disposable -- )
M: object dispose
dup disposed>> [ drop ] [ t >>disposed dispose* ] if ;
: dispose-each ( seq -- )
[
[ [ dispose ] curry [ , ] recover ] each
] { } make dup empty? [ drop ] [ peek rethrow ] if ;
: with-disposal ( object quot -- )
over [ dispose ] curry [ ] cleanup ; inline
<PRIVATE
SYMBOL: always-destructors
SYMBOL: error-destructors
: do-always-destructors ( -- )
always-destructors get <reversed> dispose-each ;
: do-error-destructors ( -- )
error-destructors get <reversed> dispose-each ;
PRIVATE>
: &dispose ( disposable -- disposable )
dup always-destructors get push ; inline
: |dispose ( disposable -- disposable )
dup error-destructors get push ; inline
: with-destructors ( quot -- )
[
V{ } clone always-destructors set
V{ } clone error-destructors set
[ do-always-destructors ]
[ do-error-destructors ]
cleanup
] with-scope ; inline

View File

@ -5,7 +5,7 @@ sequences strings vectors words quotations effects tools.test
continuations generic.standard sorting assocs definitions continuations generic.standard sorting assocs definitions
prettyprint io inspector classes.tuple classes.union prettyprint io inspector classes.tuple classes.union
classes.predicate debugger threads.private io.streams.string classes.predicate debugger threads.private io.streams.string
io.timeouts io.thread sequences.private ; io.timeouts io.thread sequences.private destructors ;
IN: inference.tests IN: inference.tests
[ ] [ [ 1 ] dataflow [ ] transform-nodes drop ] unit-test [ ] [ [ 1 ] dataflow [ ] transform-nodes drop ] unit-test

View File

@ -1,9 +1,9 @@
! Copyright (C) 2008 Daniel Ehrenberg. ! Copyright (C) 2008 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: math kernel sequences sbufs vectors namespaces growable USING: math kernel sequences sbufs vectors namespaces growable
strings io classes continuations combinators io.styles strings io classes continuations destructors combinators
io.streams.plain splitting byte-arrays sequences.private io.styles io.streams.plain splitting byte-arrays
accessors ; sequences.private accessors ;
IN: io.encodings IN: io.encodings
! The encoding descriptor protocol ! The encoding descriptor protocol

View File

@ -300,8 +300,8 @@ HELP: exists?
{ $description "Tests if the file named by " { $snippet "path" } " exists." } ; { $description "Tests if the file named by " { $snippet "path" } " exists." } ;
HELP: directory? HELP: directory?
{ $values { "path" "a pathname string" } { "?" "a boolean" } } { $values { "file-info" file-info } { "?" "a boolean" } }
{ $description "Tests if " { $snippet "path" } " names a directory." } ; { $description "Tests if " { $snippet "file-info" } " is a directory." } ;
HELP: (directory) HELP: (directory)
{ $values { "path" "a pathname string" } { "seq" "a sequence of " { $snippet "{ name dir? }" } " pairs" } } { $values { "path" "a pathname string" } { "seq" "a sequence of " { $snippet "{ name dir? }" } " pairs" } }

View File

@ -1,14 +1,14 @@
IN: io.files.tests IN: io.files.tests
USING: tools.test io.files io.files.private io threads kernel USING: tools.test io.files io.files.private io threads kernel
continuations io.encodings.ascii io.files.unique sequences continuations io.encodings.ascii io.files.unique sequences
strings accessors io.encodings.utf8 math ; strings accessors io.encodings.utf8 math destructors ;
\ exists? must-infer \ exists? must-infer
\ (exists?) must-infer \ (exists?) must-infer
[ ] [ "blahblah" temp-file dup exists? [ delete-directory ] [ drop ] if ] unit-test [ ] [ "blahblah" temp-file dup exists? [ delete-directory ] [ drop ] if ] unit-test
[ ] [ "blahblah" temp-file make-directory ] unit-test [ ] [ "blahblah" temp-file make-directory ] unit-test
[ t ] [ "blahblah" temp-file directory? ] unit-test [ t ] [ "blahblah" temp-file file-info directory? ] unit-test
[ t ] [ [ t ] [
[ temp-directory "loldir" append-path delete-directory ] ignore-errors [ temp-directory "loldir" append-path delete-directory ] ignore-errors

View File

@ -2,8 +2,8 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.backend io.files.private io hashtables kernel math USING: io.backend io.files.private io hashtables kernel math
memory namespaces sequences strings assocs arrays definitions memory namespaces sequences strings assocs arrays definitions
system combinators splitting sbufs continuations io.encodings system combinators splitting sbufs continuations destructors
io.encodings.binary init accessors math.order ; io.encodings io.encodings.binary init accessors math.order ;
IN: io.files IN: io.files
HOOK: (file-reader) io-backend ( path -- stream ) HOOK: (file-reader) io-backend ( path -- stream )
@ -172,11 +172,9 @@ SYMBOL: +socket+
SYMBOL: +unknown+ SYMBOL: +unknown+
! File metadata ! File metadata
: exists? ( path -- ? ) : exists? ( path -- ? ) normalize-path (exists?) ;
normalize-path (exists?) ;
: directory? ( path -- ? ) : directory? ( file-info -- ? ) type>> +directory+ = ;
file-info file-info-type +directory+ = ;
<PRIVATE <PRIVATE
@ -232,7 +230,7 @@ HOOK: make-directory io-backend ( path -- )
: fixup-directory ( path seq -- newseq ) : fixup-directory ( path seq -- newseq )
[ [
dup string? dup string?
[ tuck append-path directory? 2array ] [ nip ] if [ tuck append-path file-info directory? 2array ] [ nip ] if
] with map ] with map
[ first { "." ".." } member? not ] filter ; [ first { "." ".." } member? not ] filter ;

View File

@ -1,5 +1,5 @@
USING: help.markup help.syntax quotations hashtables kernel USING: help.markup help.syntax quotations hashtables kernel
classes strings continuations ; classes strings continuations destructors ;
IN: io IN: io
ARTICLE: "stream-protocol" "Stream protocol" ARTICLE: "stream-protocol" "Stream protocol"

View File

@ -1,7 +1,7 @@
! Copyright (C) 2003, 2007 Slava Pestov. ! Copyright (C) 2003, 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: hashtables generic kernel math namespaces sequences USING: hashtables generic kernel math namespaces sequences
continuations assocs io.styles ; continuations destructors assocs io.styles ;
IN: io IN: io
GENERIC: stream-readln ( stream -- str/f ) GENERIC: stream-readln ( stream -- str/f )

View File

@ -2,37 +2,37 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel kernel.private namespaces io io.encodings USING: kernel kernel.private namespaces io io.encodings
sequences math generic threads.private classes io.backend sequences math generic threads.private classes io.backend
io.files continuations byte-arrays ; io.files continuations destructors byte-arrays accessors ;
IN: io.streams.c IN: io.streams.c
TUPLE: c-writer handle ; TUPLE: c-writer handle disposed ;
C: <c-writer> c-writer : <c-writer> ( handle -- stream ) f c-writer boa ;
M: c-writer stream-write1 M: c-writer stream-write1
c-writer-handle fputc ; handle>> fputc ;
M: c-writer stream-write M: c-writer stream-write
c-writer-handle fwrite ; handle>> fwrite ;
M: c-writer stream-flush M: c-writer stream-flush
c-writer-handle fflush ; handle>> fflush ;
M: c-writer dispose M: c-writer dispose*
c-writer-handle fclose ; handle>> fclose ;
TUPLE: c-reader handle ; TUPLE: c-reader handle disposed ;
C: <c-reader> c-reader : <c-reader> ( handle -- stream ) f c-reader boa ;
M: c-reader stream-read M: c-reader stream-read
c-reader-handle fread ; handle>> fread ;
M: c-reader stream-read-partial M: c-reader stream-read-partial
stream-read ; stream-read ;
M: c-reader stream-read1 M: c-reader stream-read1
c-reader-handle fgetc ; handle>> fgetc ;
: read-until-loop ( stream delim -- ch ) : read-until-loop ( stream delim -- ch )
over stream-read1 dup [ over stream-read1 dup [
@ -45,8 +45,8 @@ M: c-reader stream-read-until
[ swap read-until-loop ] B{ } make swap [ swap read-until-loop ] B{ } make swap
over empty? over not and [ 2drop f f ] when ; over empty? over not and [ 2drop f f ] when ;
M: c-reader dispose M: c-reader dispose*
c-reader-handle fclose ; handle>> fclose ;
M: object init-io ; M: object init-io ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2006, 2008 Slava Pestov. ! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays generic assocs kernel namespaces strings USING: arrays generic assocs kernel namespaces strings
quotations io continuations accessors sequences ; quotations io continuations destructors accessors sequences ;
IN: io.streams.nested IN: io.streams.nested
TUPLE: filter-writer stream ; TUPLE: filter-writer stream ;

View File

@ -1,8 +1,8 @@
! Copyright (C) 2003, 2007 Slava Pestov. ! Copyright (C) 2003, 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io kernel math namespaces sequences sbufs strings USING: io kernel math namespaces sequences sbufs strings
generic splitting growable continuations io.streams.plain generic splitting growable continuations destructors
io.encodings math.order ; io.streams.plain io.encodings math.order ;
IN: io.streams.string IN: io.streams.string
M: growable dispose drop ; M: growable dispose drop ;

View File

@ -1,4 +1,4 @@
USING: help.markup help.syntax alien ; USING: help.markup help.syntax alien destructors ;
IN: libc IN: libc
HELP: malloc HELP: malloc
@ -36,5 +36,13 @@ HELP: with-malloc
{ $values { "size" "a positive integer" } { "quot" "a quotation with stack effect " { $snippet "( c-ptr -- )" } } } { $values { "size" "a positive integer" } { "quot" "a quotation with stack effect " { $snippet "( c-ptr -- )" } } }
{ $description "Allocates a zeroed block of " { $snippet "n" } " bytes and passes it to the quotation. When the quotation returns, the block is freed." } ; { $description "Allocates a zeroed block of " { $snippet "n" } " bytes and passes it to the quotation. When the quotation returns, the block is freed." } ;
HELP: &free
{ $values { "alien" c-ptr } }
{ $description "Marks the block of memory for unconditional deallocation at the end of the current " { $link with-destructors } " scope." } ;
HELP: |free
{ $values { "alien" c-ptr } }
{ $description "Marks the object for deallocation in the event of an error at the end of the current " { $link with-destructors } " scope." } ;
! Defined in alien-docs.factor ! Defined in alien-docs.factor
ABOUT: "malloc" ABOUT: "malloc"

View File

@ -1,8 +1,9 @@
! Copyright (C) 2004, 2005 Mackenzie Straight ! Copyright (C) 2004, 2005 Mackenzie Straight
! Copyright (C) 2007 Slava Pestov ! Copyright (C) 2007, 2008 Slava Pestov
! Copyright (C) 2007 Doug Coleman ! Copyright (C) 2007, 2008 Doug Coleman
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien assocs continuations init kernel namespaces ; USING: alien assocs continuations destructors init kernel
namespaces accessors ;
IN: libc IN: libc
<PRIVATE <PRIVATE
@ -76,3 +77,18 @@ PRIVATE>
: strlen ( alien -- len ) : strlen ( alien -- len )
"size_t" "libc" "strlen" { "char*" } alien-invoke ; "size_t" "libc" "strlen" { "char*" } alien-invoke ;
<PRIVATE
! Memory allocations
TUPLE: memory-destructor alien ;
M: memory-destructor dispose* alien>> free ;
PRIVATE>
: &free ( alien -- alien )
dup memory-destructor boa &dispose drop ; inline
: |free ( alien -- alien )
dup memory-destructor boa |dispose drop ; inline

View File

@ -1,6 +1,7 @@
USING: io.sockets io kernel math threads io.encodings.ascii USING: io.sockets io kernel math threads io.encodings.ascii
io.streams.duplex debugger tools.time prettyprint io.streams.duplex debugger tools.time prettyprint
concurrency.count-downs namespaces arrays continuations ; concurrency.count-downs namespaces arrays continuations
destructors ;
IN: benchmark.sockets IN: benchmark.sockets
SYMBOL: counter SYMBOL: counter

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: http.client checksums checksums.openssl splitting assocs USING: checksums checksums.openssl splitting assocs
kernel io.files bootstrap.image sequences io namespaces kernel io.files bootstrap.image sequences io namespaces
io.launcher math io.encodings.ascii ; io.launcher math io.encodings.ascii ;
IN: bootstrap.image.upload IN: bootstrap.image.upload

View File

@ -4,7 +4,7 @@ opengl.glu shuffle http.client vectors namespaces ui.gadgets
ui.gadgets.canvas ui.render ui splitting combinators tools.time ui.gadgets.canvas ui.render ui splitting combinators tools.time
system combinators.lib float-arrays continuations system combinators.lib float-arrays continuations
opengl.demo-support multiline ui.gestures bunny.fixed-pipeline opengl.demo-support multiline ui.gestures bunny.fixed-pipeline
bunny.cel-shaded bunny.outlined bunny.model accessors ; bunny.cel-shaded bunny.outlined bunny.model accessors destructors ;
IN: bunny IN: bunny
TUPLE: bunny-gadget model geom draw-seq draw-n ; TUPLE: bunny-gadget model geom draw-seq draw-n ;

View File

@ -1,5 +1,6 @@
USING: arrays bunny.model continuations kernel multiline opengl opengl.shaders USING: arrays bunny.model continuations destructors kernel
opengl.capabilities opengl.gl sequences sequences.lib accessors ; multiline opengl opengl.shaders opengl.capabilities opengl.gl
sequences sequences.lib accessors ;
IN: bunny.cel-shaded IN: bunny.cel-shaded
STRING: vertex-shader-source STRING: vertex-shader-source

View File

@ -1,4 +1,4 @@
USING: alien.c-types continuations kernel USING: alien.c-types continuations destructors kernel
opengl opengl.gl bunny.model ; opengl opengl.gl bunny.model ;
IN: bunny.fixed-pipeline IN: bunny.fixed-pipeline

View File

@ -2,7 +2,8 @@ USING: alien alien.c-types arrays sequences math math.vectors
math.matrices math.parser io io.files kernel opengl opengl.gl math.matrices math.parser io io.files kernel opengl opengl.gl
opengl.glu io.encodings.ascii opengl.capabilities shuffle opengl.glu io.encodings.ascii opengl.capabilities shuffle
http.client vectors splitting tools.time system combinators http.client vectors splitting tools.time system combinators
float-arrays continuations namespaces sequences.lib accessors ; float-arrays continuations destructors namespaces sequences.lib
accessors ;
IN: bunny.model IN: bunny.model
: numbers ( str -- seq ) : numbers ( str -- seq )

View File

@ -1,7 +1,7 @@
USING: arrays bunny.model bunny.cel-shaded continuations kernel USING: arrays bunny.model bunny.cel-shaded continuations
math multiline opengl opengl.shaders opengl.framebuffers destructors kernel math multiline opengl opengl.shaders
opengl.gl opengl.capabilities sequences ui.gadgets combinators opengl.framebuffers opengl.gl opengl.capabilities sequences
accessors ; ui.gadgets combinators accessors ;
IN: bunny.outlined IN: bunny.outlined
STRING: outlined-pass1-fragment-shader-main-source STRING: outlined-pass1-fragment-shader-main-source

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: cairo.ffi kernel accessors sequences USING: cairo.ffi kernel accessors sequences
namespaces fry continuations ; namespaces fry continuations destructors ;
IN: cairo IN: cairo
TUPLE: cairo-t alien ; TUPLE: cairo-t alien ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov ! Copyright (C) 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors byte-arrays alien.c-types kernel continuations USING: accessors byte-arrays alien.c-types kernel continuations
sequences io openssl openssl.libcrypto checksums ; destructors sequences io openssl openssl.libcrypto checksums ;
IN: checksums.openssl IN: checksums.openssl
ERROR: unknown-digest name ; ERROR: unknown-digest name ;

View File

@ -19,6 +19,13 @@ IN: combinators.lib.tests
[ { 1 2 } { 2 4 } { 3 8 } { 4 16 } { 5 32 } ] [ 1 2 3 4 5 [ dup 2^ 2array ] 5 napply ] unit-test [ { 1 2 } { 2 4 } { 3 8 } { 4 16 } { 5 32 } ] [ 1 2 3 4 5 [ dup 2^ 2array ] 5 napply ] unit-test
[ [ dup 2^ 2array ] 5 napply ] must-infer [ [ dup 2^ 2array ] 5 napply ] must-infer
[ { "xyc" "xyd" } ] [ "x" "y" { "c" "d" } [ 3append ] 2 nwith map ] unit-test
[ { "foo" "xbarx" } ]
[
{ "oof" "bar" } { [ reverse ] [ "x" swap "x" 3append ] } parallel-call
] unit-test
! && ! &&
[ t ] [ [ t ] [

View File

@ -4,7 +4,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel combinators fry namespaces quotations hashtables USING: kernel combinators fry namespaces quotations hashtables
sequences assocs arrays inference effects math math.ranges sequences assocs arrays inference effects math math.ranges
arrays.lib shuffle macros bake continuations ; arrays.lib shuffle macros continuations locals ;
IN: combinators.lib IN: combinators.lib
@ -20,17 +20,15 @@ MACRO: nslip ( n -- ) dup saver [ call ] rot restorer 3append ;
MACRO: nkeep ( n -- ) MACRO: nkeep ( n -- )
[ ] [ 1+ ] [ ] tri [ ] [ 1+ ] [ ] tri
[ [ , ndup ] dip , -nrot , nslip ] '[ [ , ndup ] dip , -nrot , nslip ] ;
bake ;
: 4keep ( w x y z quot -- w x y z ) 4 nkeep ; inline : 4keep ( w x y z quot -- w x y z ) 4 nkeep ; inline
MACRO: ncurry ( n -- ) [ curry ] n*quot ; MACRO: ncurry ( n -- ) [ curry ] n*quot ;
MACRO: nwith ( quot n -- ) MACRO:: nwith ( quot n -- )
tuck 1+ dup [let | n' [ n 1+ ] |
[ , -nrot [ , nrot , call ] , ncurry ] [ n' -nrot [ n' nrot quot call ] n ncurry ] ] ;
bake ;
MACRO: napply ( n -- ) MACRO: napply ( n -- )
2 [a,b] 2 [a,b]
@ -110,8 +108,8 @@ MACRO: switch ( quot -- )
! : pcall ( seq quots -- seq ) [ call ] 2map ; ! : pcall ( seq quots -- seq ) [ call ] 2map ;
MACRO: parallel-call ( quots -- ) MACRO: parallel-call ( quots -- )
[ [ unclip % r> dup >r push ] bake ] map concat [ '[ [ unclip @ ] dip [ push ] keep ] ] map concat
[ V{ } clone >r % drop r> >array ] bake ; '[ V{ } clone @ nip >array ] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! map-call and friends ! map-call and friends

View File

@ -13,7 +13,7 @@ concurrency.messaging continuations ;
[ ] [ test-node dup 1array swap (start-node) ] unit-test [ ] [ test-node dup 1array swap (start-node) ] unit-test
[ ] [ yield ] unit-test [ ] [ 100 sleep ] unit-test
[ ] [ [ ] [
[ [

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel threads boxes ; USING: kernel threads boxes accessors ;
IN: concurrency.exchangers IN: concurrency.exchangers
! Motivated by ! Motivated by
@ -12,10 +12,10 @@ TUPLE: exchanger thread object ;
<box> <box> exchanger boa ; <box> <box> exchanger boa ;
: exchange ( obj exchanger -- newobj ) : exchange ( obj exchanger -- newobj )
dup exchanger-thread box-full? [ dup thread>> occupied>> [
dup exchanger-object box> dup object>> box>
>r exchanger-thread box> resume-with r> >r thread>> box> resume-with r>
] [ ] [
[ exchanger-object >box ] keep [ object>> >box ] keep
[ exchanger-thread >box ] curry "exchange" suspend [ thread>> >box ] curry "exchange" suspend
] if ; ] if ;

View File

@ -1,7 +1,7 @@
IN: concurrency.mailboxes.tests IN: concurrency.mailboxes.tests
USING: concurrency.mailboxes concurrency.count-downs vectors USING: concurrency.mailboxes concurrency.count-downs vectors
sequences threads tools.test math kernel strings namespaces sequences threads tools.test math kernel strings namespaces
continuations calendar ; continuations calendar destructors ;
[ V{ 1 2 3 } ] [ [ V{ 1 2 3 } ] [
0 <vector> 0 <vector>

View File

@ -1,17 +1,13 @@
! Copyright (C) 2005, 2008 Chris Double, Slava Pestov. ! Copyright (C) 2005, 2008 Chris Double, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: concurrency.mailboxes IN: concurrency.mailboxes
USING: dlists threads sequences continuations USING: dlists threads sequences continuations destructors
namespaces random math quotations words kernel arrays assocs namespaces random math quotations words kernel arrays assocs
init system concurrency.conditions accessors debugger ; init system concurrency.conditions accessors debugger ;
TUPLE: mailbox threads data closed ; TUPLE: mailbox threads data disposed ;
: check-closed ( mailbox -- ) M: mailbox dispose* threads>> notify-all ;
closed>> [ "Mailbox closed" throw ] when ; inline
M: mailbox dispose
t >>closed threads>> notify-all ;
: <mailbox> ( -- mailbox ) : <mailbox> ( -- mailbox )
<dlist> <dlist> f mailbox boa ; <dlist> <dlist> f mailbox boa ;
@ -27,7 +23,7 @@ M: mailbox dispose
>r threads>> r> "mailbox" wait ; >r threads>> r> "mailbox" wait ;
: block-unless-pred ( mailbox timeout pred -- ) : block-unless-pred ( mailbox timeout pred -- )
pick check-closed pick check-disposed
pick data>> over dlist-contains? [ pick data>> over dlist-contains? [
3drop 3drop
] [ ] [
@ -35,7 +31,7 @@ M: mailbox dispose
] if ; inline ] if ; inline
: block-if-empty ( mailbox timeout -- mailbox ) : block-if-empty ( mailbox timeout -- mailbox )
over check-closed over check-disposed
over mailbox-empty? [ over mailbox-empty? [
2dup wait-for-mailbox block-if-empty 2dup wait-for-mailbox block-if-empty
] [ ] [
@ -75,7 +71,7 @@ M: mailbox dispose
f swap mailbox-get-timeout? ; inline f swap mailbox-get-timeout? ; inline
: wait-for-close-timeout ( mailbox timeout -- ) : wait-for-close-timeout ( mailbox timeout -- )
over closed>> over disposed>>
[ 2drop ] [ 2dup wait-for-mailbox wait-for-close-timeout ] if ; [ 2drop ] [ 2dup wait-for-mailbox wait-for-close-timeout ] if ;
: wait-for-close ( mailbox -- ) : wait-for-close ( mailbox -- )

View File

@ -3,7 +3,7 @@
USING: alien alien.c-types alien.strings alien.syntax kernel USING: alien alien.c-types alien.strings alien.syntax kernel
math sequences namespaces assocs init accessors continuations math sequences namespaces assocs init accessors continuations
combinators core-foundation core-foundation.run-loop combinators core-foundation core-foundation.run-loop
io.encodings.utf8 ; io.encodings.utf8 destructors ;
IN: core-foundation.fsevents IN: core-foundation.fsevents
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
@ -187,7 +187,7 @@ SYMBOL: event-stream-callbacks
dup [ call drop ] [ 3drop ] if dup [ call drop ] [ 3drop ] if
] alien-callback ; ] alien-callback ;
TUPLE: event-stream info handle closed ; TUPLE: event-stream info handle disposed ;
: <event-stream> ( quot paths latency flags -- event-stream ) : <event-stream> ( quot paths latency flags -- event-stream )
>r >r >r >r >r >r
@ -197,13 +197,10 @@ TUPLE: event-stream info handle closed ;
dup enable-event-stream dup enable-event-stream
f event-stream boa ; f event-stream boa ;
M: event-stream dispose M: event-stream dispose*
dup closed>> [ drop ] [ {
t >>closed [ info>> remove-event-source-callback ]
{ [ handle>> disable-event-stream ]
[ info>> remove-event-source-callback ] [ handle>> FSEventStreamInvalidate ]
[ handle>> disable-event-stream ] [ handle>> FSEventStreamRelease ]
[ handle>> FSEventStreamInvalidate ] } cleave ;
[ handle>> FSEventStreamRelease ]
} cleave
] if ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays assocs classes continuations kernel math USING: arrays assocs classes continuations destructors kernel math
namespaces sequences sequences.lib classes.tuple words strings namespaces sequences sequences.lib classes.tuple words strings
tools.walker accessors combinators.lib ; tools.walker accessors combinators.lib ;
IN: db IN: db
@ -25,7 +25,7 @@ GENERIC: make-db* ( seq class -- db )
GENERIC: db-open ( db -- db ) GENERIC: db-open ( db -- db )
HOOK: db-close db ( handle -- ) HOOK: db-close db ( handle -- )
: dispose-statements ( seq -- ) [ dispose drop ] assoc-each ; : dispose-statements ( assoc -- ) values dispose-each ;
: dispose-db ( db -- ) : dispose-db ( db -- )
dup db [ dup db [

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for license. ! See http://factorcode.org/license.txt for license.
USING: alien continuations io kernel prettyprint sequences USING: alien continuations destructors io kernel prettyprint
db db.mysql.ffi ; sequences db db.mysql.ffi ;
IN: db.mysql IN: db.mysql
TUPLE: mysql-db handle host user password db port ; TUPLE: mysql-db handle host user password db port ;

View File

@ -40,4 +40,4 @@ M: return-connection dispose
[ db>> ] [ pool>> ] bi return-connection ; [ db>> ] [ pool>> ] bi return-connection ;
: return-connection-later ( db pool -- ) : return-connection-later ( db pool -- )
\ return-connection boa add-always-destructor ; \ return-connection boa &dispose drop ;

View File

@ -67,12 +67,10 @@ M: postgresql-result-null summary ( obj -- str )
in-params>> [ type>> type>oid ] map >c-uint-array ; in-params>> [ type>> type>oid ] map >c-uint-array ;
: malloc-byte-array/length : malloc-byte-array/length
[ malloc-byte-array dup free-always ] [ length ] bi ; [ malloc-byte-array &free ] [ length ] bi ;
: default-param-value : default-param-value
number>string* dup [ number>string* dup [ utf8 malloc-string &free ] when 0 ;
utf8 malloc-string dup free-always
] when 0 ;
: param-values ( statement -- seq seq2 ) : param-values ( statement -- seq seq2 )
[ bind-params>> ] [ in-params>> ] bi [ bind-params>> ] [ in-params>> ] bi
@ -128,8 +126,8 @@ C: <postgresql-malloc-destructor> postgresql-malloc-destructor
M: postgresql-malloc-destructor dispose ( obj -- ) M: postgresql-malloc-destructor dispose ( obj -- )
alien>> PQfreemem ; alien>> PQfreemem ;
: postgresql-free-always ( alien -- ) : &postgresql-free ( alien -- alien )
<postgresql-malloc-destructor> add-always-destructor ; dup <postgresql-malloc-destructor> &dispose drop ; inline
: pq-get-blob ( handle row column -- obj/f ) : pq-get-blob ( handle row column -- obj/f )
[ PQgetvalue ] 3keep 3dup PQgetlength [ PQgetvalue ] 3keep 3dup PQgetlength
@ -142,7 +140,7 @@ M: postgresql-malloc-destructor dispose ( obj -- )
PQunescapeBytea dup zero? [ PQunescapeBytea dup zero? [
postgresql-result-error-message throw postgresql-result-error-message throw
] [ ] [
dup postgresql-free-always &postgresql-free
] if ] if
] keep ] keep
*uint memory>byte-array *uint memory>byte-array

View File

@ -5,7 +5,7 @@ kernel math math.parser namespaces prettyprint quotations
sequences debugger db db.postgresql.lib db.postgresql.ffi sequences debugger db db.postgresql.lib db.postgresql.ffi
db.tuples db.types tools.annotations math.ranges db.tuples db.types tools.annotations math.ranges
combinators sequences.lib classes locals words tools.walker combinators sequences.lib classes locals words tools.walker
namespaces.lib accessors random db.queries ; namespaces.lib accessors random db.queries destructors ;
USE: tools.walker USE: tools.walker
IN: db.postgresql IN: db.postgresql

View File

@ -6,7 +6,7 @@ prettyprint sequences strings classes.tuple alien.c-types
continuations db.sqlite.lib db.sqlite.ffi db.tuples continuations db.sqlite.lib db.sqlite.ffi db.tuples
words combinators.lib db.types combinators math.intervals words combinators.lib db.types combinators math.intervals
io namespaces.lib accessors vectors math.ranges random io namespaces.lib accessors vectors math.ranges random
math.bitfields.lib db.queries ; math.bitfields.lib db.queries destructors ;
USE: tools.walker USE: tools.walker
IN: db.sqlite IN: db.sqlite

View File

@ -3,7 +3,7 @@
USING: arrays assocs classes db kernel namespaces USING: arrays assocs classes db kernel namespaces
classes.tuple words sequences slots math accessors classes.tuple words sequences slots math accessors
math.parser io prettyprint db.types continuations math.parser io prettyprint db.types continuations
mirrors sequences.lib combinators.lib ; destructors mirrors sequences.lib combinators.lib ;
IN: db.tuples IN: db.tuples
: define-persistent ( class table columns -- ) : define-persistent ( class table columns -- )

View File

@ -1,20 +0,0 @@
USING: help.markup help.syntax libc kernel continuations ;
IN: destructors
HELP: free-always
{ $values { "alien" "alien returned by malloc" } }
{ $description "Adds a destructor that will " { $link free } " the alien. The free will happen whenever the quotation passed to " { $link with-destructors } " ends." }
{ $see-also free-later } ;
HELP: free-later
{ $values { "alien" "alien returned by malloc" } }
{ $description "Adds a destructor that will " { $link free } " the alien. The free will happen whenever the quotation passed to " { $link with-destructors } " errors or else the object will persist and manual cleanup is required later." }
{ $see-also free-always } ;
HELP: with-destructors
{ $values { "quot" "a quotation" } }
{ $description "Calls a quotation within a new dynamic scope. This quotation may register destructors, on any object, by wrapping the object in a destructor and implementing " { $link dispose } " on that object type. After the quotation finishes, if an error was thrown, all destructors are called and the error is then rethrown. However, if the quotation was successful, only those destructors created with an 'always cleanup' flag will be destroyed." }
{ $notes "Destructors are not allowed to throw exceptions. No exceptions." }
{ $examples
{ $code "[ 10 malloc free-always ] with-destructors" }
} ;

View File

@ -1,51 +0,0 @@
! Copyright (C) 2007 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors continuations io.backend libc
kernel namespaces sequences system vectors ;
IN: destructors
SYMBOL: error-destructors
SYMBOL: always-destructors
: add-error-destructor ( obj -- )
error-destructors get push ;
: add-always-destructor ( obj -- )
always-destructors get push ;
: do-always-destructors ( -- )
always-destructors get <reversed> dispose-each ;
: do-error-destructors ( -- )
error-destructors get <reversed> dispose-each ;
: with-destructors ( quot -- )
[
V{ } clone always-destructors set
V{ } clone error-destructors set
[ do-always-destructors ]
[ do-error-destructors ] cleanup
] with-scope ; inline
TUPLE: only-once object destroyed ;
M: only-once dispose
dup destroyed>> [ drop ] [
[ object>> dispose ] [ t >>destroyed drop ] bi
] if ;
: <only-once> f only-once boa ;
! Memory allocations
TUPLE: memory-destructor alien ;
C: <memory-destructor> memory-destructor
M: memory-destructor dispose ( obj -- )
alien>> free ;
: free-always ( alien -- )
<memory-destructor> <only-once> add-always-destructor ;
: free-later ( alien -- )
<memory-destructor> <only-once> add-error-destructor ;

View File

@ -27,7 +27,6 @@ IN: ftp.client
: ftp-command ( string -- ftp-response ) : ftp-command ( string -- ftp-response )
ftp-send read-response ; ftp-send read-response ;
: ftp-user ( ftp-client -- ftp-response ) : ftp-user ( ftp-client -- ftp-response )
user>> "USER " prepend ftp-command ; user>> "USER " prepend ftp-command ;
@ -56,21 +55,13 @@ IN: ftp.client
strings>> first strings>> first
"|" split 2 tail* first string>number ; "|" split 2 tail* first string>number ;
: ch>attribute ( ch -- symbol )
{
{ CHAR: d [ +directory+ ] }
{ CHAR: l [ +symbolic-link+ ] }
{ CHAR: - [ +regular-file+ ] }
[ drop +unknown+ ]
} case ;
TUPLE: remote-file TUPLE: remote-file
type permissions links owner group size month day time year name ; type permissions links owner group size month day time year name ;
: <remote-file> ( -- remote-file ) remote-file new ; : <remote-file> ( -- remote-file ) remote-file new ;
: parse-permissions ( remote-file str -- remote-file ) : parse-permissions ( remote-file str -- remote-file )
[ first ch>attribute >>type ] [ rest >>permissions ] bi ; [ first ch>type >>type ] [ rest >>permissions ] bi ;
: parse-list-9 ( lines -- seq ) : parse-list-9 ( lines -- seq )
[ [

View File

@ -1,6 +1,7 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors io kernel math.parser sequences ; USING: accessors arrays assocs combinators io io.files kernel
math.parser sequences strings ;
IN: ftp IN: ftp
SINGLETON: active SINGLETON: active
@ -15,6 +16,11 @@ TUPLE: ftp-client host port user password mode state ;
"anonymous" >>user "anonymous" >>user
"ftp@my.org" >>password ; "ftp@my.org" >>password ;
: reset-ftp-client ( ftp-client -- )
f >>user
f >>password
drop ;
TUPLE: ftp-response n strings parsed ; TUPLE: ftp-response n strings parsed ;
: <ftp-response> ( -- ftp-response ) : <ftp-response> ( -- ftp-response )
@ -25,3 +31,32 @@ TUPLE: ftp-response n strings parsed ;
over strings>> push ; over strings>> push ;
: ftp-send ( string -- ) write "\r\n" write flush ; : ftp-send ( string -- ) write "\r\n" write flush ;
: ftp-ipv4 1 ; inline
: ftp-ipv6 2 ; inline
: ch>type ( ch -- type )
{
{ CHAR: d [ +directory+ ] }
{ CHAR: l [ +symbolic-link+ ] }
{ CHAR: - [ +regular-file+ ] }
[ drop +unknown+ ]
} case ;
: type>ch ( type -- string )
{
{ +directory+ [ CHAR: d ] }
{ +symbolic-link+ [ CHAR: l ] }
{ +regular-file+ [ CHAR: - ] }
[ drop CHAR: - ]
} case ;
: file-info>string ( file-info name -- string )
>r [ [ type>> type>ch 1string ] [ drop "rwx------" append ] bi ]
[ size>> number>string 15 CHAR: \s pad-left ] bi r>
3array " " join ;
: directory-list ( -- seq )
"" directory keys
[ [ link-info ] keep file-info>string ] map ;

View File

@ -1,27 +1,30 @@
! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators io io.encodings.8-bit USING: accessors combinators io io.encodings.8-bit
io.files io.server io.sockets kernel math.parser io.files io.server io.sockets kernel math.parser
namespaces sequences ftp io.unix.launcher.parser namespaces sequences ftp io.unix.launcher.parser
unicode.case ; unicode.case splitting assocs ;
IN: ftp.server IN: ftp.server
SYMBOL: client SYMBOL: client
SYMBOL: stream
TUPLE: ftp-client-command string tokenized ; TUPLE: ftp-command raw tokenized ;
: <ftp-client-command> ( -- obj ) : <ftp-command> ( -- obj )
ftp-client-command new ; ftp-command new ;
: read-client-command ( -- ftp-client-command ) : read-command ( -- ftp-command )
<ftp-client-command> readln <ftp-command> readln
[ >>string ] [ tokenize-command >>tokenized ] bi ; [ >>raw ] [ tokenize-command >>tokenized ] bi ;
: (send-response) ( n string separator -- )
rot number>string write write ftp-send ;
: send-response ( ftp-response -- ) : send-response ( ftp-response -- )
[ n>> ] [ strings>> ] bi [ n>> ] [ strings>> ] bi
2dup [ but-last-slice [ "-" (send-response) ] with each ]
but-last-slice [ [ first " " (send-response) ] 2bi ;
[ number>string write "-" write ] [ ftp-send ] bi*
] with each
first [ number>string write bl ] [ ftp-send ] bi* ;
: server-response ( n string -- ) : server-response ( n string -- )
<ftp-response> <ftp-response>
@ -35,72 +38,123 @@ TUPLE: ftp-client-command string tokenized ;
: send-PASS-request ( -- ) : send-PASS-request ( -- )
331 "Please specify the password." server-response ; 331 "Please specify the password." server-response ;
: parse-USER ( ftp-client-command -- ) : anonymous-only ( -- )
530 "This FTP server is anonymous only." server-response ;
: parse-USER ( ftp-command -- )
tokenized>> second client get swap >>user drop ; tokenized>> second client get swap >>user drop ;
: send-login-response ( -- ) : send-login-response ( -- )
! client get ! client get
230 "Login successful" server-response ; 230 "Login successful" server-response ;
: parse-PASS ( ftp-client-command -- ) : parse-PASS ( ftp-command -- )
tokenized>> second client get swap >>password drop ; tokenized>> second client get swap >>password drop ;
: send-quit-response ( ftp-client-command -- ) : send-quit-response ( ftp-command -- )
drop 221 "Goodbye." server-response ; drop 221 "Goodbye." server-response ;
: unimplemented-command ( ftp-client-command -- ) : ftp-error ( string -- )
500 "Unimplemented command: " rot string>> append server-response ; 500 "Unrecognized command: " rot append server-response ;
: send-type-error ( -- )
"TYPE is binary only" ftp-error ;
: send-type-success ( string -- )
200 "Switching to " rot " mode" 3append server-response ;
: parse-TYPE ( obj -- )
tokenized>> second >upper {
{ "IMAGE" [ "Binary" send-type-success ] }
{ "I" [ "Binary" send-type-success ] }
[ drop send-type-error ]
} case ;
: pwd-response ( -- )
257 current-directory get "\"" swap "\"" 3append server-response ;
! : random-local-inet ( -- spec )
! remote-address get class new 0 >>port ;
! : handle-LIST ( -- )
! random-local-inet ascii <server> ;
: handle-STOR ( obj -- )
;
! EPRT |2|::1|62138|
! : handle-EPRT ( obj -- )
! tokenized>> second "|" split harvest ;
! : handle-EPSV ( obj -- )
! 229 "Entering Extended Passive Mode (|||"
! random-local-inet ! get port number>string
! "|)" 3append server-response ;
! LPRT 6,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,242,186
: handle-LPRT ( obj -- )
tokenized>> "," split ;
: start-directory ( -- )
150 "Here comes the directory listing." server-response ;
: finish-directory ( -- )
226 "Directory send OK." server-response ;
: send-directory-list ( stream -- )
[ directory-list write ] with-output-stream ;
: unrecognized-command ( obj -- ) raw>> ftp-error ;
: handle-client-loop ( -- ) : handle-client-loop ( -- )
<ftp-client-command> readln <ftp-command> readln
[ >>string ] [ >>raw ]
[ tokenize-command >>tokenized ] bi [ tokenize-command >>tokenized ] bi
dup tokenized>> first >upper { dup tokenized>> first >upper {
{ "USER" [ parse-USER send-PASS-request t ] } { "USER" [ parse-USER send-PASS-request t ] }
{ "PASS" [ parse-PASS send-login-response t ] } { "PASS" [ parse-PASS send-login-response t ] }
! { "ACCT" [ ] } { "ACCT" [ drop "ACCT unimplemented" ftp-error t ] }
! { "CWD" [ ] } ! { "CWD" [ ] }
! { "CDUP" [ ] } ! { "CDUP" [ ] }
! { "SMNT" [ ] } ! { "SMNT" [ ] }
! { "REIN" [ ] } ! { "REIN" [ drop client get reset-ftp-client t ] }
{ "QUIT" [ send-quit-response f ] } { "QUIT" [ send-quit-response f ] }
! { "PORT" [ ] } ! { "PORT" [ ] }
! { "PASV" [ ] } ! { "PASV" [ ] }
! { "MODE" [ ] } ! { "MODE" [ ] }
! { "TYPE" [ ] } { "TYPE" [ parse-TYPE t ] }
! { "STRU" [ ] } ! { "STRU" [ ] }
! { "ALLO" [ ] } ! { "ALLO" [ ] }
! { "REST" [ ] } ! { "REST" [ ] }
! { "STOR" [ ] } ! { "STOR" [ handle-STOR t ] }
! { "STOU" [ ] } ! { "STOU" [ ] }
! { "RETR" [ ] } ! { "RETR" [ ] }
! { "LIST" [ ] } ! { "LIST" [ drop handle-LIST t ] }
! { "NLST" [ ] } ! { "NLST" [ ] }
! { "LIST" [ ] }
! { "APPE" [ ] } ! { "APPE" [ ] }
! { "RNFR" [ ] } ! { "RNFR" [ ] }
! { "RNTO" [ ] } ! { "RNTO" [ ] }
! { "DELE" [ ] } ! { "DELE" [ ] }
! { "RMD" [ ] } ! { "RMD" [ ] }
! { "MKD" [ ] } ! { "MKD" [ ] }
! { "PWD" [ ] } { "PWD" [ drop pwd-response t ] }
! { "ABOR" [ ] } ! { "ABOR" [ ] }
! { "SYST" [ ] } ! { "SYST" [ drop ] }
! { "STAT" [ ] } ! { "STAT" [ ] }
! { "HELP" [ ] } ! { "HELP" [ ] }
! { "SITE" [ ] } ! { "SITE" [ ] }
! { "NOOP" [ ] } ! { "NOOP" [ ] }
! { "EPRT" [ ] } ! { "EPRT" [ handle-eprt ] }
! { "LPRT" [ ] } ! { "LPRT" [ handle-lprt ] }
! { "EPSV" [ ] } ! { "EPSV" [ drop handle-epsv t ] }
! { "LPSV" [ ] } ! { "LPSV" [ drop handle-lpsv t ] }
[ drop unimplemented-command t ] [ drop unrecognized-command t ]
} case [ handle-client-loop ] when ; } case [ handle-client-loop ] when ;
: handle-client ( -- ) : handle-client ( -- )

View File

@ -105,6 +105,7 @@ ARTICLE: "objects" "Objects"
"An " { $emphasis "object" } " is any datum which may be identified. All values are objects in Factor. Each object carries type information, and types are checked at runtime; Factor is dynamically typed." "An " { $emphasis "object" } " is any datum which may be identified. All values are objects in Factor. Each object carries type information, and types are checked at runtime; Factor is dynamically typed."
{ $subsection "equality" } { $subsection "equality" }
{ $subsection "math.order" } { $subsection "math.order" }
{ $subsection "destructors" }
{ $subsection "classes" } { $subsection "classes" }
{ $subsection "tuples" } { $subsection "tuples" }
{ $subsection "generic" } { $subsection "generic" }
@ -207,7 +208,8 @@ ARTICLE: "io" "Input and output"
{ $subsection "io.pipes" } { $subsection "io.pipes" }
{ $heading "Other features" } { $heading "Other features" }
{ $subsection "io.timeouts" } { $subsection "io.timeouts" }
{ $subsection "checksums" } ; { $subsection "checksums" }
{ $see-also "destructors" } ;
ARTICLE: "tools" "Developer tools" ARTICLE: "tools" "Developer tools"
{ $subsection "tools.vocabs" } { $subsection "tools.vocabs" }

View File

@ -3,7 +3,7 @@
USING: generic assocs help http io io.styles io.files continuations USING: generic assocs help http io io.styles io.files continuations
io.streams.string kernel math math.order math.parser namespaces io.streams.string kernel math math.order math.parser namespaces
quotations assocs sequences strings words html.elements quotations assocs sequences strings words html.elements
xml.entities sbufs continuations ; xml.entities sbufs continuations destructors ;
IN: html IN: html
GENERIC: browser-link-href ( presented -- href ) GENERIC: browser-link-href ( presented -- href )

View File

@ -45,6 +45,7 @@ blah
[ [
TUPLE{ request TUPLE{ request
protocol: http
port: 80 port: 80
method: "GET" method: "GET"
path: "/bar" path: "/bar"
@ -84,6 +85,7 @@ Host: www.sex.com
[ [
TUPLE{ request TUPLE{ request
protocol: http
port: 80 port: 80
method: "HEAD" method: "HEAD"
path: "/bar" path: "/bar"

View File

@ -265,7 +265,7 @@ cookies ;
pick query>> set-at ; pick query>> set-at ;
: chop-hostname ( str -- str' ) : chop-hostname ( str -- str' )
":" split1 nip ":" split1 "//" ?head drop nip
CHAR: / over index over length or tail CHAR: / over index over length or tail
dup empty? [ drop "/" ] when ; dup empty? [ drop "/" ] when ;
@ -440,7 +440,7 @@ M: https protocol-addr
dup host>> [ dup host>> [
[ protocol>> protocol>string write "://" write ] [ protocol>> protocol>string write "://" write ]
[ host>> url-encode write ":" write ] [ host>> url-encode write ":" write ]
[ port>> number>string write ] [ [ port>> ] [ protocol>> http-port or ] bi number>string write ]
tri tri
] [ drop ] if ] [ drop ] if
] ]

View File

@ -58,7 +58,7 @@ M: user-saver dispose
user>> dup changed?>> [ users update-user ] [ drop ] if ; user>> dup changed?>> [ users update-user ] [ drop ] if ;
: save-user-after ( user -- ) : save-user-after ( user -- )
<user-saver> add-always-destructor ; <user-saver> &dispose drop ;
: login-template ( name -- template ) : login-template ( name -- template )
"resource:extra/http/server/auth/login/" swap ".xml" "resource:extra/http/server/auth/login/" swap ".xml"

View File

@ -6,6 +6,7 @@ IN: http.server.tests
[ [
<request> <request>
http >>protocol
"www.apple.com" >>host "www.apple.com" >>host
"/xxx/bar" >>path "/xxx/bar" >>path
{ { "a" "b" } } >>query { { "a" "b" } } >>query

View File

@ -102,7 +102,7 @@ M: session-saver dispose
] [ drop ] if ; ] [ drop ] if ;
: save-session-after ( session -- ) : save-session-after ( session -- )
<session-saver> add-always-destructor ; <session-saver> &dispose drop ;
: existing-session ( path session -- response ) : existing-session ( path session -- response )
[ session set ] [ save-session-after ] bi [ session set ] [ save-session-after ] bi

View File

@ -91,7 +91,7 @@ TUPLE: file-responder root hook special allow-listings ;
: serve-object ( filename -- response ) : serve-object ( filename -- response )
serving-path dup exists? serving-path dup exists?
[ dup directory? [ serve-directory ] [ serve-file ] if ] [ dup file-info directory? [ serve-directory ] [ serve-file ] if ]
[ drop <404> ] [ drop <404> ]
if ; if ;

View File

@ -151,20 +151,20 @@ M: process timed-out kill-process ;
M: object run-pipeline-element M: object run-pipeline-element
[ >process swap >>stdout swap >>stdin run-detached ] [ >process swap >>stdout swap >>stdin run-detached ]
[ drop [ [ close-handle ] when* ] bi@ ] [ drop [ [ dispose ] when* ] bi@ ]
3bi 3bi
wait-for-process ; wait-for-process ;
: <process-reader*> ( process encoding -- process stream ) : <process-reader*> ( process encoding -- process stream )
[ [
>r (pipe) { >r (pipe) {
[ add-error-destructor ] [ |dispose drop ]
[ [
swap >process swap >process
[ swap out>> or ] change-stdout [ swap out>> or ] change-stdout
run-detached run-detached
] ]
[ out>> close-handle ] [ out>> dispose ]
[ in>> <input-port> ] [ in>> <input-port> ]
} cleave r> <decoder> } cleave r> <decoder>
] with-destructors ; ] with-destructors ;
@ -175,13 +175,13 @@ M: object run-pipeline-element
: <process-writer*> ( process encoding -- process stream ) : <process-writer*> ( process encoding -- process stream )
[ [
>r (pipe) { >r (pipe) {
[ add-error-destructor ] [ |dispose drop ]
[ [
swap >process swap >process
[ swap in>> or ] change-stdout [ swap in>> or ] change-stdout
run-detached run-detached
] ]
[ in>> close-handle ] [ in>> dispose ]
[ out>> <output-port> ] [ out>> <output-port> ]
} cleave r> <encoder> } cleave r> <encoder>
] with-destructors ; ] with-destructors ;
@ -192,14 +192,14 @@ M: object run-pipeline-element
: <process-stream*> ( process encoding -- process stream ) : <process-stream*> ( process encoding -- process stream )
[ [
>r (pipe) (pipe) { >r (pipe) (pipe) {
[ [ add-error-destructor ] bi@ ] [ [ |dispose drop ] bi@ ]
[ [
rot >process rot >process
[ swap out>> or ] change-stdout [ swap out>> or ] change-stdout
[ swap in>> or ] change-stdin [ swap in>> or ] change-stdin
run-detached run-detached
] ]
[ [ out>> close-handle ] [ in>> close-handle ] bi* ] [ [ out>> dispose ] [ in>> dispose ] bi* ]
[ [ in>> <input-port> ] [ out>> <output-port> ] bi* ] [ [ in>> <input-port> ] [ out>> <output-port> ] bi* ]
} 2cleave r> <encoder-duplex> } 2cleave r> <encoder-duplex>
] with-destructors ; ] with-destructors ;

View File

@ -1,4 +1,5 @@
USING: help.markup help.syntax alien math continuations ; USING: help.markup help.syntax alien math continuations
destructors ;
IN: io.mmap IN: io.mmap
HELP: mapped-file HELP: mapped-file

View File

@ -1,23 +1,19 @@
! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov. ! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: continuations io.backend kernel quotations sequences USING: continuations destructors io.backend kernel quotations
system alien alien.accessors accessors sequences.private ; sequences system alien alien.accessors accessors
sequences.private ;
IN: io.mmap IN: io.mmap
TUPLE: mapped-file address handle length closed ; TUPLE: mapped-file address handle length disposed ;
: check-closed ( mapped-file -- mapped-file ) M: mapped-file length dup check-disposed length>> ;
dup closed>> [
"Mapped file is closed" throw
] when ; inline
M: mapped-file length check-closed length>> ;
M: mapped-file nth-unsafe M: mapped-file nth-unsafe
check-closed address>> swap alien-unsigned-1 ; dup check-disposed address>> swap alien-unsigned-1 ;
M: mapped-file set-nth-unsafe M: mapped-file set-nth-unsafe
check-closed address>> swap set-alien-unsigned-1 ; dup check-disposed address>> swap set-alien-unsigned-1 ;
INSTANCE: mapped-file sequence INSTANCE: mapped-file sequence
@ -29,10 +25,7 @@ HOOK: (mapped-file) io-backend ( path length -- address handle )
HOOK: close-mapped-file io-backend ( mmap -- ) HOOK: close-mapped-file io-backend ( mmap -- )
M: mapped-file dispose ( mmap -- ) M: mapped-file dispose* ( mmap -- ) close-mapped-file ;
dup closed>> [ drop ] [
t >>closed close-mapped-file
] if ;
: with-mapped-file ( path length quot -- ) : with-mapped-file ( path length quot -- )
>r <mapped-file> r> with-disposal ; inline >r <mapped-file> r> with-disposal ; inline

View File

@ -1,5 +1,5 @@
IN: io.monitors IN: io.monitors
USING: help.markup help.syntax continuations USING: help.markup help.syntax continuations destructors
concurrency.mailboxes quotations ; concurrency.mailboxes quotations ;
HELP: with-monitors HELP: with-monitors

View File

@ -1,7 +1,7 @@
IN: io.monitors.tests IN: io.monitors.tests
USING: io.monitors tools.test io.files system sequences USING: io.monitors tools.test io.files system sequences
continuations namespaces concurrency.count-downs kernel io continuations namespaces concurrency.count-downs kernel io
threads calendar prettyprint ; threads calendar prettyprint destructors ;
os { winnt linux macosx } member? [ os { winnt linux macosx } member? [
[ [

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.backend kernel continuations namespaces sequences USING: io.backend kernel continuations destructors namespaces
assocs hashtables sorting arrays threads boxes io.timeouts sequences assocs hashtables sorting arrays threads boxes
accessors concurrency.mailboxes ; io.timeouts accessors concurrency.mailboxes ;
IN: io.monitors IN: io.monitors
HOOK: init-monitors io-backend ( -- ) HOOK: init-monitors io-backend ( -- )

View File

@ -1,7 +1,6 @@
USING: accessors math kernel namespaces continuations USING: accessors math kernel namespaces continuations
io.files io.monitors io.monitors.recursive io.backend io.files io.monitors io.monitors.recursive io.backend
concurrency.mailboxes concurrency.mailboxes tools.test destructors ;
tools.test ;
IN: io.monitors.recursive.tests IN: io.monitors.recursive.tests
\ pump-thread must-infer \ pump-thread must-infer

View File

@ -1,13 +1,14 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors sequences assocs arrays continuations combinators kernel USING: accessors sequences assocs arrays continuations
threads concurrency.messaging concurrency.mailboxes concurrency.promises destructors combinators kernel threads concurrency.messaging
io.files io.monitors debugger ; concurrency.mailboxes concurrency.promises io.files io.monitors
debugger ;
IN: io.monitors.recursive IN: io.monitors.recursive
! Simulate recursive monitors on platforms that don't have them ! Simulate recursive monitors on platforms that don't have them
TUPLE: recursive-monitor < monitor children thread ready ; TUPLE: recursive-monitor < monitor children thread ready disposed ;
: notify? ( -- ? ) monitor tget ready>> promise-fulfilled? ; : notify? ( -- ? ) monitor tget ready>> promise-fulfilled? ;
@ -35,13 +36,10 @@ DEFER: add-child-monitor
: remove-child-monitor ( monitor -- ) : remove-child-monitor ( monitor -- )
monitor tget children>> delete-at* [ dispose ] [ drop ] if ; monitor tget children>> delete-at* [ dispose ] [ drop ] if ;
M: recursive-monitor dispose M: recursive-monitor dispose*
dup queue>> closed>> [ [ "stop" swap thread>> send-synchronous drop ]
drop [ queue>> dispose ]
] [ bi ;
[ "stop" swap thread>> send-synchronous drop ]
[ queue>> dispose ] bi
] if ;
: stop-pump ( -- ) : stop-pump ( -- )
monitor tget children>> [ nip dispose ] assoc-each ; monitor tget children>> [ nip dispose ] assoc-each ;

View File

@ -1,4 +1,4 @@
USING: help.markup help.syntax continuations io ; USING: help.markup help.syntax continuations destructors io ;
IN: io.pipes IN: io.pipes
HELP: pipe HELP: pipe

View File

@ -1,6 +1,6 @@
USING: io io.pipes io.streams.string io.encodings.utf8 USING: io io.pipes io.streams.string io.encodings.utf8
io.streams.duplex io.encodings io.timeouts namespaces io.streams.duplex io.encodings io.timeouts namespaces
continuations tools.test kernel calendar ; continuations tools.test kernel calendar destructors ;
IN: io.pipes.tests IN: io.pipes.tests
[ "Hello" ] [ [ "Hello" ] [

View File

@ -9,24 +9,21 @@ IN: io.pipes
TUPLE: pipe in out ; TUPLE: pipe in out ;
M: pipe dispose ( pipe -- ) M: pipe dispose ( pipe -- )
[ in>> close-handle ] [ out>> close-handle ] bi ; [ in>> dispose ] [ out>> dispose ] bi ;
HOOK: (pipe) io-backend ( -- pipe ) HOOK: (pipe) io-backend ( -- pipe )
: <pipe> ( encoding -- stream ) : <pipe> ( encoding -- stream )
[ [
>r (pipe) >r (pipe) |dispose
[ add-error-destructor ] [ in>> <input-port> ] [ out>> <output-port> ] bi
[ in>> <input-port> ]
[ out>> <output-port> ]
tri
r> <encoder-duplex> r> <encoder-duplex>
] with-destructors ; ] with-destructors ;
<PRIVATE <PRIVATE
: ?reader [ <input-port> dup add-always-destructor ] [ input-stream get ] if* ; : ?reader [ <input-port> &dispose ] [ input-stream get ] if* ;
: ?writer [ <output-port> dup add-always-destructor ] [ output-stream get ] if* ; : ?writer [ <output-port> &dispose ] [ output-stream get ] if* ;
GENERIC: run-pipeline-element ( input-fd output-fd obj -- quot ) GENERIC: run-pipeline-element ( input-fd output-fd obj -- quot )
@ -38,7 +35,7 @@ M: callable run-pipeline-element
: <pipes> ( n -- pipes ) : <pipes> ( n -- pipes )
[ [
[ (pipe) dup add-error-destructor ] replicate [ (pipe) |dispose ] replicate
T{ pipe } [ prefix ] [ suffix ] bi T{ pipe } [ prefix ] [ suffix ] bi
2 <clumps> 2 <clumps>
] with-destructors ; ] with-destructors ;

View File

@ -1,5 +1,6 @@
USING: io io.buffers io.backend help.markup help.syntax kernel USING: io io.buffers io.backend help.markup help.syntax kernel
byte-arrays sbufs words continuations byte-vectors classes ; byte-arrays sbufs words continuations destructors
byte-vectors classes ;
IN: io.ports IN: io.ports
ARTICLE: "io.ports" "Non-blocking I/O implementation" ARTICLE: "io.ports" "Non-blocking I/O implementation"

View File

@ -10,7 +10,7 @@ IN: io.ports
SYMBOL: default-buffer-size SYMBOL: default-buffer-size
64 1024 * default-buffer-size set-global 64 1024 * default-buffer-size set-global
TUPLE: port handle error timeout closed ; TUPLE: port handle error timeout disposed ;
M: port timeout timeout>> ; M: port timeout timeout>> ;
@ -18,21 +18,6 @@ M: port set-timeout (>>timeout) ;
GENERIC: init-handle ( handle -- ) GENERIC: init-handle ( handle -- )
GENERIC: close-handle ( handle -- )
TUPLE: handle-destructor handle ;
C: <handle-destructor> handle-destructor
M: handle-destructor dispose ( obj -- )
handle>> close-handle ;
: close-always ( handle -- )
<handle-destructor> <only-once> add-always-destructor ;
: close-later ( handle -- )
<handle-destructor> <only-once> add-error-destructor ;
: <port> ( handle class -- port ) : <port> ( handle class -- port )
new new
swap dup init-handle >>handle ; inline swap dup init-handle >>handle ; inline
@ -40,14 +25,6 @@ M: handle-destructor dispose ( obj -- )
: pending-error ( port -- ) : pending-error ( port -- )
[ f ] change-error drop [ throw ] when* ; [ f ] change-error drop [ throw ] when* ;
ERROR: port-closed-error port ;
M: port-closed-error summary
drop "Port has been closed" ;
: check-closed ( port -- port )
dup closed>> [ port-closed-error ] when ;
TUPLE: buffered-port < port buffer ; TUPLE: buffered-port < port buffer ;
: <buffered-port> ( handle class -- port ) : <buffered-port> ( handle class -- port )
@ -69,7 +46,7 @@ HOOK: (wait-to-read) io-backend ( port -- )
[ f >>eof drop f ] r> if ; inline [ f >>eof drop f ] r> if ; inline
M: input-port stream-read1 M: input-port stream-read1
check-closed dup check-disposed
dup wait-to-read [ buffer>> buffer-pop ] unless-eof ; dup wait-to-read [ buffer>> buffer-pop ] unless-eof ;
: read-step ( count port -- byte-array/f ) : read-step ( count port -- byte-array/f )
@ -77,7 +54,7 @@ M: input-port stream-read1
[ dupd buffer>> buffer-read ] unless-eof nip ; [ dupd buffer>> buffer-read ] unless-eof nip ;
M: input-port stream-read-partial ( max stream -- byte-array/f ) M: input-port stream-read-partial ( max stream -- byte-array/f )
check-closed dup check-disposed
>r 0 max >integer r> read-step ; >r 0 max >integer r> read-step ;
: read-loop ( count port accum -- ) : read-loop ( count port accum -- )
@ -92,7 +69,7 @@ M: input-port stream-read-partial ( max stream -- byte-array/f )
] if ; ] if ;
M: input-port stream-read M: input-port stream-read
check-closed dup check-disposed
>r 0 max >fixnum r> >r 0 max >fixnum r>
2dup read-step dup [ 2dup read-step dup [
pick over length > [ pick over length > [
@ -115,12 +92,12 @@ TUPLE: output-port < buffered-port ;
tuck buffer>> can-write? [ drop ] [ stream-flush ] if ; tuck buffer>> can-write? [ drop ] [ stream-flush ] if ;
M: output-port stream-write1 M: output-port stream-write1
check-closed dup check-disposed
1 over wait-to-write 1 over wait-to-write
buffer>> byte>buffer ; buffer>> byte>buffer ;
M: output-port stream-write M: output-port stream-write
check-closed dup check-disposed
over length over buffer>> buffer-size > [ over length over buffer>> buffer-size > [
[ buffer>> buffer-size <groups> ] [ buffer>> buffer-size <groups> ]
[ [ stream-write ] curry ] bi [ [ stream-write ] curry ] bi
@ -136,15 +113,13 @@ HOOK: (wait-to-write) io-backend ( port -- )
dup buffer>> buffer-empty? [ drop ] [ (wait-to-write) ] if ; dup buffer>> buffer-empty? [ drop ] [ (wait-to-write) ] if ;
M: output-port stream-flush ( port -- ) M: output-port stream-flush ( port -- )
check-closed dup check-disposed
[ flush-port ] [ pending-error ] bi ; [ flush-port ] [ pending-error ] bi ;
GENERIC: close-port ( port -- ) M: output-port dispose*
M: output-port close-port
[ flush-port ] [ call-next-method ] bi ; [ flush-port ] [ call-next-method ] bi ;
M: buffered-port close-port M: buffered-port dispose*
[ call-next-method ] [ call-next-method ]
[ [ [ buffer-free ] when* f ] change-buffer drop ] [ [ [ buffer-free ] when* f ] change-buffer drop ]
bi ; bi ;
@ -153,14 +128,10 @@ HOOK: cancel-io io-backend ( port -- )
M: port timed-out cancel-io ; M: port timed-out cancel-io ;
M: port close-port M: port dispose* [ cancel-io ] [ handle>> dispose ] bi ;
[ cancel-io ] [ handle>> close-handle ] bi ;
M: port dispose
dup closed>> [ drop ] [ t >>closed close-port ] if ;
: <ports> ( read-handle write-handle -- input-port output-port ) : <ports> ( read-handle write-handle -- input-port output-port )
[ [
[ <input-port> dup add-error-destructor ] [ <input-port> |dispose ]
[ <output-port> dup add-error-destructor ] bi* [ <output-port> |dispose ] bi*
] with-destructors ; ] with-destructors ;

View File

@ -1,19 +1,19 @@
! Copyright (C) 2003, 2008 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io io.sockets io.files io.streams.duplex logging USING: io io.sockets io.files io.streams.duplex logging
continuations kernel math math.parser namespaces parser continuations destructors kernel math math.parser namespaces
sequences strings prettyprint debugger quotations calendar parser sequences strings prettyprint debugger quotations
threads concurrency.combinators assocs fry ; calendar threads concurrency.combinators assocs fry ;
IN: io.server IN: io.server
SYMBOL: servers SYMBOL: servers
SYMBOL: remote-address
<PRIVATE <PRIVATE
LOG: accepted-connection NOTICE LOG: accepted-connection NOTICE
SYMBOL: remote-address
: with-connection ( client remote quot -- ) : with-connection ( client remote quot -- )
'[ '[
, [ remote-address set ] [ accepted-connection ] bi , [ remote-address set ] [ accepted-connection ] bi

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel symbols namespaces continuations USING: accessors kernel symbols namespaces continuations
io.sockets sequences ; destructors io.sockets sequences ;
IN: io.sockets.secure IN: io.sockets.secure
SYMBOL: ssl-backend SYMBOL: ssl-backend

View File

@ -1,5 +1,5 @@
USING: help.markup help.syntax io io.backend threads USING: help.markup help.syntax io io.backend threads
strings byte-arrays continuations quotations ; strings byte-arrays continuations destructors quotations ;
IN: io.sockets IN: io.sockets
ARTICLE: "network-addressing" "Address specifiers" ARTICLE: "network-addressing" "Address specifiers"

View File

@ -151,10 +151,12 @@ M: inet6 parse-sockaddr
M: f parse-sockaddr nip ; M: f parse-sockaddr nip ;
GENERIC# (wait-to-connect) 1 ( client-out handle remote -- sockaddr ) GENERIC: (get-local-address) ( handle remote -- sockaddr )
: wait-to-connect ( client-out handle remote -- local ) : get-local-address ( handle remote -- local )
[ (wait-to-connect) ] keep parse-sockaddr ; [ (get-local-address) ] keep parse-sockaddr ;
GENERIC: establish-connection ( client-out remote -- )
GENERIC: ((client)) ( remote -- handle ) GENERIC: ((client)) ( remote -- handle )
@ -164,12 +166,13 @@ M: array (client) [ (client) 3array ] attempt-all first3 ;
M: object (client) ( remote -- client-in client-out local ) M: object (client) ( remote -- client-in client-out local )
[ [
[ ((client)) ] keep
[ [
((client)) >r dup <ports> [ |dispose ] bi@ dup r>
dup <ports> establish-connection
2dup [ add-error-destructor ] bi@ ]
dup dup handle>> [ get-local-address ]
] keep wait-to-connect 2bi
] with-destructors ; ] with-destructors ;
: <client> ( remote encoding -- stream local ) : <client> ( remote encoding -- stream local )
@ -184,26 +187,26 @@ SYMBOL: local-address
TUPLE: server-port < port addr encoding ; TUPLE: server-port < port addr encoding ;
: check-server-port ( port -- port ) : check-server-port ( port -- port )
check-closed dup check-disposed
dup server-port? [ "Not a server port" throw ] unless ; inline dup server-port? [ "Not a server port" throw ] unless ; inline
GENERIC: (server) ( addrspec -- handle sockaddr ) GENERIC: (server) ( addrspec -- handle )
: <server> ( addrspec encoding -- server ) : <server> ( addrspec encoding -- server )
>r [ (server) ] keep parse-sockaddr >r
swap server-port <port> [ (server) ] keep
swap >>addr [ drop server-port <port> ] [ get-local-address ] 2bi
r> >>encoding ; >>addr r> >>encoding ;
GENERIC: (accept) ( server addrspec -- handle remote ) GENERIC: (accept) ( server addrspec -- handle )
: accept ( server -- client remote ) : accept ( server -- client remote )
check-server-port [
[ dup addr>> (accept) ] keep dup addr>>
tuck [ (accept) ] keep
[ [ dup <ports> ] [ encoding>> ] bi* <encoder-duplex> ] [ drop dup <ports> ] [ get-local-address ] 2bi
[ addr>> parse-sockaddr ] -rot
2bi* ; ] keep encoding>> <encoder-duplex> swap ;
TUPLE: datagram-port < port addr ; TUPLE: datagram-port < port addr ;
@ -213,7 +216,7 @@ HOOK: (datagram) io-backend ( addr -- datagram )
dup (datagram) datagram-port <port> swap >>addr ; dup (datagram) datagram-port <port> swap >>addr ;
: check-datagram-port ( port -- port ) : check-datagram-port ( port -- port )
check-closed dup check-disposed
dup datagram-port? [ "Not a datagram port" throw ] unless ; inline dup datagram-port? [ "Not a datagram port" throw ] unless ; inline
HOOK: (receive) io-backend ( datagram -- packet addrspec ) HOOK: (receive) io-backend ( datagram -- packet addrspec )

View File

@ -18,9 +18,6 @@ HELP: <duplex-stream>
{ $values { "in" "an input stream" } { "out" "an output stream" } { "stream" " a duplex stream" } } { $values { "in" "an input stream" } { "out" "an output stream" } { "stream" " a duplex stream" } }
{ $description "Creates a duplex stream. Writing to a duplex stream will write to " { $snippet "out" } ", and reading from a duplex stream will read from " { $snippet "in" } ". Closing a duplex stream closes both the input and output streams." } ; { $description "Creates a duplex stream. Writing to a duplex stream will write to " { $snippet "out" } ", and reading from a duplex stream will read from " { $snippet "in" } ". Closing a duplex stream closes both the input and output streams." } ;
HELP: stream-closed-twice
{ $error-description "This error is thrown when performing an I/O operation on a " { $link duplex-stream } " which has been closed with " { $link dispose } "." } ;
HELP: with-stream HELP: with-stream
{ $values { "stream" duplex-stream } { "quot" quotation } } { $values { "stream" duplex-stream } { "quot" quotation } }
{ $description "Calls the quotation in a new dynamic scope, with both " { $link input-stream } " and " { $link output-stream } " rebound to " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ; { $description "Calls the quotation in a new dynamic scope, with both " { $link input-stream } " and " { $link output-stream } " rebound to " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ;

View File

@ -1,18 +1,13 @@
USING: io.streams.duplex io io.streams.string USING: io.streams.duplex io io.streams.string
kernel continuations tools.test ; kernel continuations tools.test destructors accessors ;
IN: io.streams.duplex.tests IN: io.streams.duplex.tests
! Test duplex stream close behavior ! Test duplex stream close behavior
TUPLE: closing-stream closed? ; TUPLE: closing-stream < disposable ;
: <closing-stream> closing-stream new ; : <closing-stream> closing-stream new ;
M: closing-stream dispose M: closing-stream dispose* drop ;
dup closing-stream-closed? [
"Closing twice!" throw
] [
t swap set-closing-stream-closed?
] if ;
TUPLE: unclosable-stream ; TUPLE: unclosable-stream ;
@ -30,14 +25,14 @@ M: unclosable-stream dispose
<unclosable-stream> <closing-stream> [ <unclosable-stream> <closing-stream> [
<duplex-stream> <duplex-stream>
[ dup dispose ] [ 2drop ] recover [ dup dispose ] [ 2drop ] recover
] keep closing-stream-closed? ] keep disposed>>
] unit-test ] unit-test
[ t ] [ [ t ] [
<closing-stream> [ <unclosable-stream> <closing-stream> [ <unclosable-stream>
<duplex-stream> <duplex-stream>
[ dup dispose ] [ 2drop ] recover [ dup dispose ] [ 2drop ] recover
] keep closing-stream-closed? ] keep disposed>>
] unit-test ] unit-test
[ "Hey" ] [ [ "Hey" ] [

View File

@ -1,50 +1,33 @@
! Copyright (C) 2005, 2008 Slava Pestov. ! Copyright (C) 2005, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel continuations io io.encodings io.encodings.private USING: kernel continuations destructors io io.encodings
io.timeouts debugger inspector listener accessors delegate io.encodings.private io.timeouts debugger inspector listener
delegate.protocols ; accessors delegate delegate.protocols ;
IN: io.streams.duplex IN: io.streams.duplex
! We ensure that the stream can only be closed once, to preserve ! We ensure that the stream can only be closed once, to preserve
! integrity of duplex I/O ports. ! integrity of duplex I/O ports.
TUPLE: duplex-stream in out closed ; TUPLE: duplex-stream in out ;
: <duplex-stream> ( in out -- stream ) C: <duplex-stream> duplex-stream
f duplex-stream boa ;
ERROR: stream-closed-twice ; CONSULT: input-stream-protocol duplex-stream in>> ;
M: stream-closed-twice summary CONSULT: output-stream-protocol duplex-stream out>> ;
drop "Attempt to perform I/O on closed stream" ;
<PRIVATE
: check-closed ( stream -- stream )
dup closed>> [ stream-closed-twice ] when ; inline
: in ( duplex -- stream ) check-closed in>> ;
: out ( duplex -- stream ) check-closed out>> ;
PRIVATE>
CONSULT: input-stream-protocol duplex-stream in ;
CONSULT: output-stream-protocol duplex-stream out ;
M: duplex-stream set-timeout M: duplex-stream set-timeout
[ in set-timeout ] [ out set-timeout ] 2bi ; [ in>> set-timeout ] [ out>> set-timeout ] 2bi ;
M: duplex-stream dispose M: duplex-stream dispose
#! The output stream is closed first, in case both streams #! The output stream is closed first, in case both streams
#! are attached to the same file descriptor, the output #! are attached to the same file descriptor, the output
#! buffer needs to be flushed before we close the fd. #! buffer needs to be flushed before we close the fd.
dup closed>> [ [
t >>closed [ out>> &dispose drop ]
[ dup out>> dispose ] [ in>> &dispose drop ]
[ dup in>> dispose ] [ ] cleanup bi
] unless drop ; ] with-destructors ;
: <encoder-duplex> ( stream-in stream-out encoding -- duplex ) : <encoder-duplex> ( stream-in stream-out encoding -- duplex )
tuck re-encode >r re-decode r> <duplex-stream> ; tuck re-encode >r re-decode r> <duplex-stream> ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: io.streams.null IN: io.streams.null
USING: kernel io io.timeouts io.streams.duplex continuations ; USING: kernel io io.timeouts io.streams.duplex destructors ;
TUPLE: null-stream ; TUPLE: null-stream ;

View File

@ -4,20 +4,18 @@ USING: alien generic assocs kernel kernel.private math
io.ports sequences strings structs sbufs threads unix io.ports sequences strings structs sbufs threads unix
vectors io.buffers io.backend io.encodings math.parser vectors io.buffers io.backend io.encodings math.parser
continuations system libc qualified namespaces io.timeouts continuations system libc qualified namespaces io.timeouts
io.encodings.utf8 accessors inspector combinators ; io.encodings.utf8 destructors accessors inspector combinators ;
QUALIFIED: io QUALIFIED: io
IN: io.unix.backend IN: io.unix.backend
! I/O tasks ! I/O tasks
GENERIC: handle-fd ( handle -- fd ) GENERIC: handle-fd ( handle -- fd )
TUPLE: fd fd closed ; TUPLE: fd fd disposed ;
: <fd> ( n -- fd ) f fd boa ; : <fd> ( n -- fd ) f fd boa ;
M: fd dispose M: fd dispose* fd>> close-file ;
dup closed>>
[ drop ] [ t >>closed fd>> close-file ] if ;
M: fd handle-fd fd>> ; M: fd handle-fd fd>> ;
@ -112,8 +110,6 @@ M: fd init-handle ( fd -- )
[ F_SETFL O_NONBLOCK fcntl drop ] [ F_SETFL O_NONBLOCK fcntl drop ]
[ F_SETFD FD_CLOEXEC fcntl drop ] bi ; [ F_SETFD FD_CLOEXEC fcntl drop ] bi ;
M: fd close-handle ( fd -- ) dispose ;
! Readers ! Readers
: eof ( reader -- ) : eof ( reader -- )
dup buffer>> buffer-empty? [ t >>eof ] when drop ; dup buffer>> buffer-empty? [ t >>eof ] when drop ;

View File

@ -33,7 +33,7 @@ M: unix (file-writer) ( path -- stream )
: open-append ( path -- fd ) : open-append ( path -- fd )
[ [
append-flags file-mode open-file dup close-later append-flags file-mode open-file |dispose
dup 0 SEEK_END lseek io-error dup 0 SEEK_END lseek io-error
] with-destructors ; ] with-destructors ;

View File

@ -6,6 +6,6 @@ IN: io.unix.files.unique
{ O_RDWR O_CREAT O_EXCL } flags ; { O_RDWR O_CREAT O_EXCL } flags ;
M: unix (make-unique-file) ( path -- ) M: unix (make-unique-file) ( path -- )
open-unique-flags file-mode open dup io-error close ; open-unique-flags file-mode open-file close-file ;
M: unix temporary-path ( -- path ) "/tmp" ; M: unix temporary-path ( -- path ) "/tmp" ;

View File

@ -1,7 +1,7 @@
IN: io.unix.launcher.tests IN: io.unix.launcher.tests
USING: io.files tools.test io.launcher arrays io namespaces USING: io.files tools.test io.launcher arrays io namespaces
continuations math io.encodings.binary io.encodings.ascii continuations math io.encodings.binary io.encodings.ascii
accessors kernel sequences io.encodings.utf8 ; accessors kernel sequences io.encodings.utf8 destructors ;
[ ] [ [ ] [
[ "launcher-test-1" temp-file delete-file ] ignore-errors [ "launcher-test-1" temp-file delete-file ] ignore-errors

View File

@ -12,7 +12,7 @@ SYMBOL: watches
SYMBOL: inotify SYMBOL: inotify
TUPLE: linux-monitor < monitor wd inotify watches ; TUPLE: linux-monitor < monitor wd inotify watches disposed ;
: <linux-monitor> ( wd path mailbox -- monitor ) : <linux-monitor> ( wd path mailbox -- monitor )
linux-monitor new-monitor linux-monitor new-monitor
@ -54,14 +54,12 @@ M: linux (monitor) ( path recursive? mailbox -- monitor )
IN_CHANGE_EVENTS swap add-watch IN_CHANGE_EVENTS swap add-watch
] if ; ] if ;
M: linux-monitor dispose ( monitor -- ) M: linux-monitor dispose* ( monitor -- )
dup inotify>> closed>> [ drop ] [ [ [ wd>> ] [ watches>> ] bi delete-at ]
[ [ wd>> ] [ watches>> ] bi delete-at ] [
[ [ inotify>> handle>> ] [ wd>> ] bi
[ inotify>> handle>> ] [ wd>> ] bi inotify_rm_watch io-error
inotify_rm_watch io-error ] bi ;
] bi
] if ;
: ignore-flags? ( mask -- ? ) : ignore-flags? ( mask -- ? )
{ {

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.unix.bsd io.backend io.monitors core-foundation.fsevents USING: io.unix.bsd io.backend io.monitors core-foundation.fsevents
continuations kernel sequences namespaces arrays system locals continuations kernel sequences namespaces arrays system locals
accessors ; accessors destructors ;
IN: io.unix.macosx IN: io.unix.macosx
TUPLE: macosx-monitor < monitor handle ; TUPLE: macosx-monitor < monitor handle ;

View File

@ -9,7 +9,7 @@ IN: io.unix.mmap
:: mmap-open ( length prot flags path -- alien fd ) :: mmap-open ( length prot flags path -- alien fd )
[ [
f length prot flags f length prot flags
path open-r/w dup close-later path open-r/w |dispose
[ 0 mmap dup MAP_FAILED = [ (io-error) ] when ] keep [ 0 mmap dup MAP_FAILED = [ (io-error) ] when ] keep
] with-destructors ; ] with-destructors ;

View File

@ -92,12 +92,12 @@ M: ssl parse-sockaddr addrspec>> parse-sockaddr <ssl> ;
2dup SSL_connect check-connect-response dup 2dup SSL_connect check-connect-response dup
[ >r over r> wait-for-port do-ssl-connect ] [ 3drop ] if ; [ >r over r> wait-for-port do-ssl-connect ] [ 3drop ] if ;
M: ssl-handle (wait-to-connect) M: ssl establish-connection ( client-out remote -- )
addrspec>> addrspec>>
[ >r file>> r> (wait-to-connect) ] [ establish-connection ]
[ drop handle>> do-ssl-connect ] [ drop dup handle>> do-ssl-connect ]
[ drop t >>connected 2drop ] [ drop t >>connected drop ]
3tri ; 2tri ;
M: ssl (server) addrspec>> (server) ; M: ssl (server) addrspec>> (server) ;
@ -117,12 +117,8 @@ M: ssl (server) addrspec>> (server) ;
M: ssl (accept) M: ssl (accept)
[ [
addrspec>> addrspec>> (accept) |dispose <ssl-socket> |dispose
(accept) >r
dup close-later
<ssl-socket> dup close-later
dup do-ssl-accept dup do-ssl-accept
r>
] with-destructors ; ] with-destructors ;
: check-shutdown-response ( handle r -- event ) : check-shutdown-response ( handle r -- event )

59
extra/io/unix/sockets/sockets.factor Executable file → Normal file
View File

@ -13,7 +13,7 @@ EXCLUDE: io.sockets => accept ;
IN: io.unix.sockets IN: io.unix.sockets
: socket-fd ( domain type -- fd ) : socket-fd ( domain type -- fd )
0 socket dup io-error <fd> [ close-later ] [ init-handle ] [ ] tri ; 0 socket dup io-error <fd> |dispose dup init-handle ;
: set-socket-option ( fd level opt -- ) : set-socket-option ( fd level opt -- )
>r >r handle-fd r> r> 1 <int> "int" heap-size setsockopt io-error ; >r >r handle-fd r> r> 1 <int> "int" heap-size setsockopt io-error ;
@ -22,24 +22,34 @@ M: unix addrinfo-error ( n -- )
dup zero? [ drop ] [ gai_strerror throw ] if ; dup zero? [ drop ] [ gai_strerror throw ] if ;
! Client sockets - TCP and Unix domain ! Client sockets - TCP and Unix domain
: init-client-socket ( fd -- ) M: object (get-local-address) ( handle remote -- sockaddr )
SOL_SOCKET SO_OOBINLINE set-socket-option ;
: get-socket-name ( fd addrspec -- sockaddr )
>r handle-fd r> empty-sockaddr/size >r handle-fd r> empty-sockaddr/size
[ getsockname io-error ] 2keep drop ; [ getsockname io-error ] 2keep drop ;
: get-peer-name ( fd addrspec -- sockaddr ) : init-client-socket ( fd -- )
>r handle-fd r> empty-sockaddr/size SOL_SOCKET SO_OOBINLINE set-socket-option ;
[ getpeername io-error ] 2keep drop ;
M: fd (wait-to-connect) : wait-to-connect ( port -- )
>r >r +output+ wait-for-port r> r> get-socket-name ; dup handle>> handle-fd f 0 write
{
{ [ 0 = ] [ drop ] }
{ [ err_no EAGAIN = ] [ dup +output+ wait-for-port wait-to-connect ] }
{ [ err_no EINTR = ] [ wait-to-connect ] }
[ (io-error) ]
} cond ;
M: object establish-connection ( client-out remote -- )
[ drop ] [ [ handle>> handle-fd ] [ make-sockaddr/size ] bi* connect ] 2bi
{
{ [ 0 = ] [ drop ] }
{ [ err_no EINPROGRESS = ] [
[ +output+ wait-for-port ] [ wait-to-connect ] bi
] }
[ (io-error) ]
} cond ;
M: object ((client)) ( addrspec -- fd ) M: object ((client)) ( addrspec -- fd )
[ protocol-family SOCK_STREAM socket-fd ] [ make-sockaddr/size ] bi protocol-family SOCK_STREAM socket-fd dup init-client-socket ;
>r >r dup handle-fd r> r> connect zero? err_no EINPROGRESS = or
[ dup init-client-socket ] [ (io-error) ] if ;
! Server sockets - TCP and Unix domain ! Server sockets - TCP and Unix domain
: init-server-socket ( fd -- ) : init-server-socket ( fd -- )
@ -50,27 +60,22 @@ M: object ((client)) ( addrspec -- fd )
dup init-server-socket dup init-server-socket
dup handle-fd rot make-sockaddr/size bind io-error ; dup handle-fd rot make-sockaddr/size bind io-error ;
M: object (server) ( addrspec -- handle sockaddr ) M: object (server) ( addrspec -- handle )
[ [
[ SOCK_STREAM server-socket-fd
SOCK_STREAM server-socket-fd dup handle-fd 10 listen io-error
dup handle-fd 10 listen io-error
dup
] keep
get-socket-name
] with-destructors ; ] with-destructors ;
: do-accept ( server addrspec -- fd remote ) : do-accept ( server addrspec -- fd )
[ handle>> handle-fd ] [ empty-sockaddr/size ] bi* [ handle>> handle-fd ] [ empty-sockaddr/size ] bi* accept ; inline
[ accept ] 2keep drop ; inline
M: object (accept) ( server addrspec -- fd remote ) M: object (accept) ( server addrspec -- fd )
2dup do-accept 2dup do-accept
{ {
{ [ over 0 >= ] [ { [ drop ] [ drop ] [ <fd> ] [ ] } spread ] } { [ dup 0 >= ] [ 2nip <fd> ] }
{ [ err_no EINTR = ] [ 2drop (accept) ] } { [ err_no EINTR = ] [ drop (accept) ] }
{ [ err_no EAGAIN = ] [ { [ err_no EAGAIN = ] [
2drop drop
[ drop +input+ wait-for-port ] [ drop +input+ wait-for-port ]
[ (accept) ] [ (accept) ]
2bi 2bi

View File

@ -1,7 +1,7 @@
USING: io.files io.sockets io kernel threads USING: io.files io.sockets io kernel threads
namespaces tools.test continuations strings byte-arrays namespaces tools.test continuations strings byte-arrays
sequences prettyprint system io.encodings.binary io.encodings.ascii sequences prettyprint system io.encodings.binary io.encodings.ascii
io.streams.duplex ; io.streams.duplex destructors ;
IN: io.unix.tests IN: io.unix.tests
! Unix domain stream sockets ! Unix domain stream sockets

View File

@ -68,6 +68,11 @@ SYMBOLS: +read-only+ +hidden+ +system+
! [ BY_HANDLE_FILE_INFORMATION-ftCreationTime FILETIME>timestamp ] ! [ BY_HANDLE_FILE_INFORMATION-ftCreationTime FILETIME>timestamp ]
[ BY_HANDLE_FILE_INFORMATION-ftLastWriteTime FILETIME>timestamp ] [ BY_HANDLE_FILE_INFORMATION-ftLastWriteTime FILETIME>timestamp ]
! [ BY_HANDLE_FILE_INFORMATION-ftLastAccessTime FILETIME>timestamp ] ! [ BY_HANDLE_FILE_INFORMATION-ftLastAccessTime FILETIME>timestamp ]
! [ BY_HANDLE_FILE_INFORMATION-nNumberOfLinks ]
! [
! [ BY_HANDLE_FILE_INFORMATION-nFileIndexLow ]
! [ BY_HANDLE_FILE_INFORMATION-nFileIndexHigh ] bi >64bit
! ]
} cleave } cleave
\ file-info boa ; \ file-info boa ;

View File

@ -8,17 +8,29 @@ windows.shell32 windows.types windows.winsock splitting
continuations math.bitfields system accessors ; continuations math.bitfields system accessors ;
IN: io.windows IN: io.windows
TUPLE: win32-file handle ptr ; TUPLE: win32-handle handle disposed ;
C: <win32-file> win32-file : new-win32-handle ( handle class -- win32-handle )
new swap >>handle ;
: <win32-handle> ( handle -- win32-handle )
win32-handle new-win32-handle ;
M: win32-handle dispose* ( handle -- )
handle>> CloseHandle drop ;
TUPLE: win32-file handle ptr disposed ;
: <win32-file> ( handle -- win32-file )
win32-file new-win32-handle ;
M: win32-file init-handle ( handle -- )
drop ;
HOOK: CreateFile-flags io-backend ( DWORD -- DWORD ) HOOK: CreateFile-flags io-backend ( DWORD -- DWORD )
HOOK: FileArgs-overlapped io-backend ( port -- overlapped/f ) HOOK: FileArgs-overlapped io-backend ( port -- overlapped/f )
HOOK: add-completion io-backend ( port -- ) HOOK: add-completion io-backend ( port -- )
M: windows normalize-directory ( string -- string )
normalize-path "\\" ?tail drop "\\*" append ;
: share-mode ( -- fixnum ) : share-mode ( -- fixnum )
{ {
FILE_SHARE_READ FILE_SHARE_READ
@ -34,179 +46,3 @@ M: windows normalize-directory ( string -- string )
: security-attributes-inherit ( -- obj ) : security-attributes-inherit ( -- obj )
default-security-attributes default-security-attributes
TRUE over set-SECURITY_ATTRIBUTES-bInheritHandle ; foldable TRUE over set-SECURITY_ATTRIBUTES-bInheritHandle ; foldable
M: win32-file init-handle ( handle -- )
drop ;
M: win32-file close-handle ( handle -- )
handle>> close-handle ;
M: alien close-handle ( handle -- )
CloseHandle drop ;
! Clean up resources (open handle) if add-completion fails
: open-file ( path access-mode create-mode flags -- handle )
[
>r >r share-mode security-attributes-inherit r> r>
CreateFile-flags f CreateFile
dup invalid-handle?
|close-handle
dup add-completion
] with-destructors ;
: open-pipe-r/w ( path -- handle )
{ GENERIC_READ GENERIC_WRITE } flags
OPEN_EXISTING 0 open-file ;
: open-read ( path -- handle length )
GENERIC_READ OPEN_EXISTING 0 open-file 0 ;
: open-write ( path -- handle length )
GENERIC_WRITE CREATE_ALWAYS 0 open-file 0 ;
: (open-append) ( path -- handle )
GENERIC_WRITE OPEN_ALWAYS 0 open-file ;
: open-existing ( path -- handle )
{ GENERIC_READ GENERIC_WRITE } flags
share-mode
f
OPEN_EXISTING
FILE_FLAG_BACKUP_SEMANTICS
f CreateFileW dup win32-error=0/f ;
: maybe-create-file ( path -- handle ? )
#! return true if file was just created
{ GENERIC_READ GENERIC_WRITE } flags
share-mode
f
OPEN_ALWAYS
0 CreateFile-flags
f CreateFileW dup win32-error=0/f
GetLastError ERROR_ALREADY_EXISTS = not ;
: set-file-pointer ( handle length method -- )
>r dupd d>w/w <uint> r> SetFilePointer
INVALID_SET_FILE_POINTER = [
CloseHandle "SetFilePointer failed" throw
] when drop ;
HOOK: open-append os ( path -- handle length )
TUPLE: FileArgs
hFile lpBuffer nNumberOfBytesToRead
lpNumberOfBytesRet lpOverlapped ;
C: <FileArgs> FileArgs
: make-FileArgs ( port -- <FileArgs> )
{
[ handle>> handle>> ]
[ buffer>> ]
[ buffer>> buffer-length ]
[ drop "DWORD" <c-object> ]
[ FileArgs-overlapped ]
} cleave <FileArgs> ;
: setup-read ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRead lpOverlapped )
{
[ hFile>> ]
[ lpBuffer>> buffer-end ]
[ lpBuffer>> buffer-capacity ]
[ lpNumberOfBytesRet>> ]
[ lpOverlapped>> ]
} cleave ;
: setup-write ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToWrite lpNumberOfBytesWritten lpOverlapped )
{
[ hFile>> ]
[ lpBuffer>> buffer@ ]
[ lpBuffer>> buffer-length ]
[ lpNumberOfBytesRet>> ]
[ lpOverlapped>> ]
} cleave ;
M: windows (file-reader) ( path -- stream )
open-read <win32-file> <input-port> ;
M: windows (file-writer) ( path -- stream )
open-write <win32-file> <output-port> ;
M: windows (file-appender) ( path -- stream )
open-append <win32-file> <output-port> ;
M: windows move-file ( from to -- )
[ normalize-path ] bi@ MoveFile win32-error=0/f ;
M: windows delete-file ( path -- )
normalize-path DeleteFile win32-error=0/f ;
M: windows copy-file ( from to -- )
dup parent-directory make-directories
[ normalize-path ] bi@ 0 CopyFile win32-error=0/f ;
M: windows make-directory ( path -- )
normalize-path
f CreateDirectory win32-error=0/f ;
M: windows delete-directory ( path -- )
normalize-path
RemoveDirectory win32-error=0/f ;
HOOK: WSASocket-flags io-backend ( -- DWORD )
TUPLE: win32-socket < win32-file overlapped ;
: <win32-socket> ( handle overlapped -- win32-socket )
win32-socket new
swap >>overlapped
swap >>handle ;
: open-socket ( family type -- socket )
0 f 0 WSASocket-flags WSASocket dup socket-error ;
USE: windows.winsock
: init-sockaddr ( port# addrspec -- sockaddr )
dup sockaddr-type <c-object>
[ swap protocol-family swap set-sockaddr-in-family ] keep
[ >r htons r> set-sockaddr-in-port ] keep ;
: server-sockaddr ( port# addrspec -- sockaddr )
init-sockaddr
[ INADDR_ANY swap set-sockaddr-in-addr ] keep ;
: bind-socket ( socket sockaddr addrspec -- )
[ server-sockaddr ] keep
sockaddr-type heap-size bind socket-error ;
TUPLE: socket-destructor alien ;
C: <socket-destructor> socket-destructor
M: socket-destructor dispose ( obj -- )
alien>> closesocket drop ;
: |close-socket ( handle -- handle )
dup <socket-destructor> <only-once> |dispose drop ;
: server-fd ( addrspec type -- fd )
>r dup protocol-family r> open-socket |close-socket
dup rot make-sockaddr/size bind socket-error ;
USE: namespaces
! http://support.microsoft.com/kb/127144
! NOTE: Possibly tweak this because of SYN flood attacks
: listen-backlog ( -- n ) HEX: 7fffffff ; inline
: listen-on-socket ( socket -- )
listen-backlog listen winsock-return-check ;
M: win32-socket dispose ( stream -- )
handle>> closesocket drop ;
M: windows addrinfo-error ( n -- )
winsock-return-check ;
: tcp-socket ( addrspec -- socket )
protocol-family SOCK_STREAM open-socket ;

View File

@ -3,7 +3,7 @@
USING: arrays calendar combinators channels concurrency.messaging fry io USING: arrays calendar combinators channels concurrency.messaging fry io
io.encodings.8-bit io.sockets kernel math namespaces sequences io.encodings.8-bit io.sockets kernel math namespaces sequences
sequences.lib splitting strings threads sequences.lib splitting strings threads
continuations classes.tuple ascii accessors ; continuations destructors classes.tuple ascii accessors ;
IN: irc IN: irc
! utils ! utils
@ -143,7 +143,7 @@ SYMBOL: irc-client
" hostname servername :irc.factor" irc-print ; " hostname servername :irc.factor" irc-print ;
: CONNECT ( server port -- stream ) : CONNECT ( server port -- stream )
<inet> latin1 <client> ; <inet> latin1 <client> drop ;
: JOIN ( channel password -- ) : JOIN ( channel password -- )
"JOIN " irc-write "JOIN " irc-write

View File

@ -76,6 +76,7 @@ PRIVATE>
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SYMBOL: lisp-env SYMBOL: lisp-env
ERROR: no-such-var var ;
: init-env ( -- ) : init-env ( -- )
H{ } clone lisp-env set ; H{ } clone lisp-env set ;
@ -84,7 +85,7 @@ SYMBOL: lisp-env
swap lisp-env get set-at ; swap lisp-env get set-at ;
: lisp-get ( name -- word ) : lisp-get ( name -- word )
lisp-env get at ; dup lisp-env get at [ ] [ no-such-var ] ?if ;
: funcall ( quot sym -- * ) : funcall ( quot sym -- * )
dup lisp-symbol? [ name>> lisp-get ] when call ; inline dup lisp-symbol? [ name>> lisp-get ] when call ; inline

View File

@ -1,10 +1,10 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces kernel io calendar sequences io.files USING: namespaces kernel io calendar sequences io.files
io.sockets continuations prettyprint assocs math.parser io.sockets continuations destructors prettyprint assocs
words debugger math combinators concurrency.messaging math.parser words debugger math combinators
threads arrays init math.ranges strings calendar.format concurrency.messaging threads arrays init math.ranges strings
io.encodings.utf8 ; calendar.format io.encodings.utf8 ;
IN: logging.server IN: logging.server
: log-root ( -- string ) : log-root ( -- string )

View File

@ -103,8 +103,7 @@ M: openssl <ssl-context> ( config -- context )
maybe-init-ssl maybe-init-ssl
[ [
dup method>> ssl-method SSL_CTX_new dup method>> ssl-method SSL_CTX_new
dup ssl-error V{ } clone openssl-context boa dup ssl-error V{ } clone openssl-context boa |dispose
dup add-error-destructor
{ {
[ load-certificate-chain ] [ load-certificate-chain ]
[ set-default-password ] [ set-default-password ]
@ -138,14 +137,11 @@ M: ssl-handle init-handle file>> init-handle ;
HOOK: ssl-shutdown io-backend ( handle -- ) HOOK: ssl-shutdown io-backend ( handle -- )
M: ssl-handle close-handle M: ssl-handle dispose*
dup disposed>> [ drop ] [ [ ssl-shutdown ]
t >>disposed [ handle>> SSL_free ]
[ ssl-shutdown ] [ file>> dispose ]
[ handle>> SSL_free ] tri ;
[ file>> close-handle ]
tri
] if ;
ERROR: certificate-verify-error result ; ERROR: certificate-verify-error result ;

View File

@ -1,7 +1,6 @@
USING: accessors alien.c-types byte-arrays continuations USING: accessors alien.c-types byte-arrays continuations
kernel windows windows.advapi32 init namespaces random kernel windows windows.advapi32 init namespaces random
destructors locals ; destructors locals ;
USE: tools.walker
IN: random.windows IN: random.windows
TUPLE: windows-rng provider type ; TUPLE: windows-rng provider type ;
@ -36,9 +35,8 @@ M: windows-crypto-context dispose ( tuple -- )
M: windows-rng random-bytes* ( n tuple -- bytes ) M: windows-rng random-bytes* ( n tuple -- bytes )
[ [
[ provider>> ] [ type>> ] bi [ provider>> ] [ type>> ] bi
windows-crypto-context windows-crypto-context &dispose
dup add-always-destructor handle>> handle>> swap dup <byte-array>
swap dup <byte-array>
[ CryptGenRandom win32-error=0/f ] keep [ CryptGenRandom win32-error=0/f ] keep
] with-destructors ; ] with-destructors ;

View File

@ -3,7 +3,7 @@
USING: accessors arrays combinators combinators.cleave combinators.lib USING: accessors arrays combinators combinators.cleave combinators.lib
continuations db db.tuples db.types db.sqlite kernel math continuations db db.tuples db.types db.sqlite kernel math
math.parser namespaces parser sets sequences sequences.deep math.parser namespaces parser sets sequences sequences.deep
sequences.lib strings words ; sequences.lib strings words destructors ;
IN: semantic-db IN: semantic-db
TUPLE: node id content ; TUPLE: node id content ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2007 Chris Double, Doug Coleman. ! Copyright (C) 2007 Chris Double, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences namespaces math inference.transforms USING: kernel sequences namespaces math inference.transforms
combinators macros quotations math.ranges bake ; combinators macros quotations math.ranges fry ;
IN: shuffle IN: shuffle
@ -19,7 +19,7 @@ MACRO: ndrop ( n -- ) [ drop ] n*quot ;
: nnip ( n -- ) swap >r ndrop r> ; inline : nnip ( n -- ) swap >r ndrop r> ; inline
MACRO: ntuck ( n -- ) 2 + [ dup , -nrot ] bake ; MACRO: ntuck ( n -- ) 2 + '[ dup , -nrot ] ;
: 2swap ( x y z t -- z t x y ) rot >r rot r> ; inline : 2swap ( x y z t -- z t x y ) rot >r rot r> ; inline

Some files were not shown because too many files have changed in this diff Show More