]> gitweb.factorcode.org Git - factor.git/blob - core/destructors/destructors-docs.factor
Fixes #2966
[factor.git] / core / destructors / destructors-docs.factor
1 USING: classes help.markup help.syntax io quotations sequences ;
2 IN: destructors
3
4 HELP: debug-leaks?
5 { $var-description "When this variable is on, " { $link new-disposable } " stores the current continuation in the " { $link disposable } "'s " { $slot "continuation" } " slot." }
6 { $see-also "tools.destructors" } ;
7
8 HELP: disposable
9 { $class-description "Parent class for disposable resources. This class has two slots:"
10     { $slots
11         { "disposed" { "A boolean value, set to true by " { $link dispose } ". Assert that it is false with " { $link check-disposed } "." } }
12         { "continuation" { "The current continuation at construction time, for debugging. Set by " { $link new-disposable } " if " { $link debug-leaks? } " is on." } }
13     }
14 "New instances must be constructed with " { $link new-disposable } " and subclasses must implement " { $link dispose* } "." } ;
15
16 HELP: new-disposable
17 { $values { "class" class } { "disposable" disposable } }
18 { $description "Constructs a new instance of a subclass of " { $link disposable } ". This sets the " { $slot "id" } " slot, registers the new object with the global " { $link disposables } " set, and if " { $link debug-leaks? } " is on, stores the current continuation in the " { $slot "continuation" } " slot." } ;
19
20 HELP: dispose
21 { $values { "disposable" "a disposable object" } }
22 { $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on."
23 $nl
24 "No further operations can be performed on a disposable object after this call."
25 $nl
26 "Disposing an object which has already been disposed should have no effect, and in particular it should not fail with an error. To help implement this pattern, inherit from the " { $link disposable } " class and implement the " { $link dispose* } " method instead." }
27 { $notes "You must dispose of disposable objects after you are finished working with them, to avoid leaking operating system resources. A convenient way to automate this is by using the " { $link with-disposal } " word."
28 $nl
29 "The default implementation assumes the object has a " { $snippet "disposed" } " slot. If the slot is set to " { $link f } ", it calls " { $link dispose* } " and sets the slot to " { $link t } "." } ;
30
31 HELP: dispose*
32 { $values { "disposable" "a disposable object" } }
33 { $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on." }
34 { $notes
35     "This word should not be called directly. It can be implemented on objects with a " { $slot "disposed" } " slot to ensure that the object is only disposed once."
36 } ;
37
38 HELP: with-disposal
39 { $values { "object" "a disposable object" } { "quot" { $quotation ( object -- ) } } }
40 { $description "Calls the quotation, disposing the object with " { $link dispose } " after the quotation returns or if it throws an error." } ;
41
42 HELP: with-destructors
43 { $values { "quot" quotation } }
44 { $description "Calls a quotation within a new dynamic scope. This quotation may register destructors using " { $link &dispose } " or " { $link |dispose } ". The former registers a destructor that will always run whether or not the quotation threw an error, and the latter registers a destructor that only runs if the quotation throws an error. Destructors are run in reverse order from the order in which they were registered." }
45 { $notes
46     "Destructors generalize " { $link with-disposal } ". The following two lines are equivalent, except that the second line establishes a new dynamic scope:"
47     { $code
48         "[ X ] with-disposal"
49         "[ &dispose X ] with-destructors"
50     }
51 }
52 { $examples
53     { $code "[ 10 malloc &free ] with-destructors" }
54 } ;
55
56 HELP: &dispose
57 { $values { "disposable" "a disposable object" } }
58 { $description "Marks the object for unconditional disposal at the end of the current " { $link with-destructors } " scope." } ;
59
60 HELP: |dispose
61 { $values { "disposable" "a disposable object" } }
62 { $description "Marks the object for disposal in the event of an error at the end of the current " { $link with-destructors } " scope." } ;
63
64 HELP: dispose-each
65 { $values
66      { "seq" sequence } }
67 { $description "Attempts to dispose of each element of a sequence and collects all of the errors into a sequence. If any errors are thrown during disposal, the last error is rethrown after all objects have been disposed." } ;
68
69 HELP: disposables
70 { $var-description "Global variable holding all disposable objects which have not been disposed of yet. The " { $link new-disposable } " word adds objects here, and the " { $link dispose } " method on disposables removes them. The " { $link "tools.destructors" } " vocabulary provides some words for working with this data." }
71 { $see-also "tools.destructors" } ;
72
73 ARTICLE: "destructors-anti-patterns" "Resource disposal anti-patterns"
74 "Words which create objects corresponding to external resources should always be used with " { $link with-disposal } ". The following code is wrong:"
75 { $code
76     "<external-resource> ... do stuff ... dispose"
77 }
78 "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." ;
79
80 ARTICLE: "destructors-using" "Using destructors"
81 "Disposing of an object:"
82 { $subsections dispose }
83 "Utility word for scoped disposal:"
84 { $subsections with-disposal }
85 "Utility word for disposing multiple objects:"
86 { $subsections dispose-each }
87 "Utility words for more complex disposal patterns:"
88 { $subsections
89     with-destructors
90     &dispose
91     |dispose
92 } ;
93
94 ARTICLE: "destructors-extending" "Writing new destructors"
95 "Superclass for disposable objects:"
96 { $subsections disposable }
97 "Parameterized constructor for disposable objects:"
98 { $subsections new-disposable }
99 "Generic disposal word:"
100 { $subsections dispose* }
101 "Global set of disposable objects:"
102 { $subsections disposables } ;
103
104 ARTICLE: "destructors" "Deterministic resource disposal"
105 "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."
106 { $subsections
107     "destructors-using"
108     "destructors-extending"
109     "destructors-anti-patterns"
110 }
111 { $see-also "tools.destructors" } ;
112
113 ABOUT: "destructors"