]> gitweb.factorcode.org Git - factor.git/blob - core/destructors/destructors-docs.factor
docs: change $subsection to $subsections
[factor.git] / core / destructors / destructors-docs.factor
1 USING: help.markup help.syntax libc kernel continuations io
2 sequences classes ;
3 IN: destructors
4
5 HELP: debug-leaks?
6 { $var-description "When this variable is on, " { $link new-disposable } " stores the current continuation in the " { $link disposable } "'s " { $slot "continuation" } " slot." }
7 { $see-also "tools.destructors" } ;
8
9 HELP: disposable
10 { $class-description "Parent class for disposable resources. This class has three slots:"
11     { $list
12         { { $slot "disposed" } " - boolean. Set to true by " { $link dispose } ". Assert that it is false with " { $link check-disposed } "." }
13         { { $slot "id" } " - unique identifier. Set by " { $link new-disposable } "." }
14         { { $slot "continuation" } " - current continuation at construction time, for debugging. Set by " { $link new-disposable } " if " { $link debug-leaks? } " is on." }
15     }
16 "New instances must be constructed with " { $link new-disposable } " and subclasses must implement " { $link dispose* } "." } ;
17
18 HELP: new-disposable
19 { $values { "class" class } { "disposable" disposable } }
20 { $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." } ;
21
22 HELP: dispose
23 { $values { "disposable" "a disposable object" } }
24 { $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on."
25 $nl
26 "No further operations can be performed on a disposable object after this call."
27 $nl
28 "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." }
29 { $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."
30 $nl
31 "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 } "." } ;
32
33 HELP: dispose*
34 { $values { "disposable" "a disposable object" } }
35 { $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on." }
36 { $notes
37     "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."
38 } ;
39
40 HELP: with-disposal
41 { $values { "object" "a disposable object" } { "quot" { $quotation "( object -- )" } } }
42 { $description "Calls the quotation, disposing the object with " { $link dispose } " after the quotation returns or if it throws an error." } ;
43
44 HELP: with-destructors
45 { $values { "quot" "a quotation" } }
46 { $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." }
47 { $notes
48     "Destructors generalize " { $link with-disposal } ". The following two lines are equivalent, except that the second line establishes a new dynamic scope:"
49     { $code
50         "[ X ] with-disposal"
51         "[ &dispose X ] with-destructors"
52     }
53 }
54 { $examples
55     { $code "[ 10 malloc &free ] with-destructors" }
56 } ;
57
58 HELP: &dispose
59 { $values { "disposable" "a disposable object" } }
60 { $description "Marks the object for unconditional disposal at the end of the current " { $link with-destructors } " scope." } ;
61
62 HELP: |dispose
63 { $values { "disposable" "a disposable object" } }
64 { $description "Marks the object for disposal in the event of an error at the end of the current " { $link with-destructors } " scope." } ;
65
66 HELP: dispose-each
67 { $values
68      { "seq" sequence } }
69 { $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." } ;
70
71 HELP: disposables
72 { $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." }
73 { $see-also "tools.destructors" } ;
74
75 ARTICLE: "destructors-anti-patterns" "Resource disposal anti-patterns"
76 "Words which create objects corresponding to external resources should always be used with " { $link with-disposal } ". The following code is wrong:"
77 { $code
78     "<external-resource> ... do stuff ... dispose"
79 }
80 "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." ;
81
82 ARTICLE: "destructors-using" "Using destructors"
83 "Disposing of an object:"
84 { $subsections dispose }
85 "Utility word for scoped disposal:"
86 { $subsections with-disposal }
87 "Utility word for disposing multiple objects:"
88 { $subsections dispose-each }
89 "Utility words for more complex disposal patterns:"
90 { $subsections
91     with-destructors
92     &dispose
93     |dispose
94 } ;
95
96 ARTICLE: "destructors-extending" "Writing new destructors"
97 "Superclass for disposable objects:"
98 { $subsections disposable }
99 "Parametrized constructor for disposable objects:"
100 { $subsections new-disposable }
101 "Generic disposal word:"
102 { $subsections dispose* }
103 "Global set of disposable objects:"
104 { $subsections disposables } ;
105
106 ARTICLE: "destructors" "Deterministic resource disposal"
107 "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."
108 { $subsections
109     "destructors-using"
110     "destructors-extending"
111     "destructors-anti-patterns"
112 }
113 { $see-also "tools.destructors" } ;
114
115 ABOUT: "destructors"