]> gitweb.factorcode.org Git - factor.git/blob - basis/threads/threads-docs.factor
io.streams.tee: more tests
[factor.git] / basis / threads / threads-docs.factor
1 USING: assocs boxes deques dlists heaps help.markup help.syntax
2 init kernel kernel.private namespaces quotations strings system
3 threads.private ;
4 IN: threads
5
6 ARTICLE: "threads-start/stop" "Starting and stopping threads"
7 "Spawning new threads:"
8 { $subsections
9     spawn
10     spawn-server
11 }
12 "Creating and spawning a thread can be factored out into two separate steps:"
13 { $subsections
14     <thread>
15     (spawn)
16 }
17 "Threads stop either when the quotation given to " { $link spawn } " returns, or when the following word is called:"
18 { $subsections stop }
19 "If the image is saved and started again, all runnable threads are stopped. Vocabularies wishing to have a background thread always running should use " { $link add-startup-hook } "." ;
20
21 ARTICLE: "threads-yield" "Yielding and suspending threads"
22 "Yielding to other threads:"
23 { $subsections yield }
24 "Sleeping for a period of time:"
25 { $subsections sleep }
26 "Interrupting sleep:"
27 { $subsections interrupt }
28 "Threads can be suspended and woken up at some point in the future when a condition is satisfied:"
29 { $subsections
30     suspend
31     resume
32     resume-with
33 } ;
34
35 ARTICLE: "thread-state" "Thread-local state and variables"
36 "Threads form a class of objects:"
37 { $subsections thread }
38 "The current thread:"
39 { $subsections self }
40 "Thread-local variables:"
41 { $subsections
42     tnamespace
43     tget
44     tset
45     tchange
46 }
47 "Each thread has its own independent set of thread-local variables and newly-spawned threads begin with an empty set."
48 $nl
49 "Global hashtable of all threads, keyed by " { $snippet "id" } ":"
50 { $subsections threads }
51 "Threads have an identity independent of continuations. If a continuation is reified in one thread and then reflected in another thread, the code running in that continuation will observe a change in the value output by " { $link self } "." ;
52
53 ARTICLE: "thread-impl" "Thread implementation"
54 "Thread implementation:"
55 { $subsections
56     run-queue
57     sleep-queue
58 } ;
59
60 ARTICLE: "threads" "Co-operative threads"
61 "Factor supports co-operative threads. A thread will yield while waiting for input/output operations to complete, or when a yield has been explicitly requested."
62 $nl
63 "Words for working with threads are in the " { $vocab-link "threads" } " vocabulary."
64 { $subsections
65     "threads-start/stop"
66     "threads-yield"
67     "thread-state"
68     "thread-impl"
69 } ;
70
71 ABOUT: "threads"
72
73 HELP: thread
74 { $class-description "A thread. The slots are as follows:"
75     { $slots
76       {
77           "id"
78           "a unique identifier assigned to each thread."
79       }
80       {
81           "exit-handler"
82           { "a " { $link quotation } " run when the thread is being stopped." }
83       }
84       {
85           "name"
86           { "the name passed to " { $link spawn } "." }
87       }
88       {
89           "quot"
90           { "the initial quotation passed to " { $link spawn } "." }
91       }
92       {
93           "runnable"
94           { "whether the thread is runnable. Initially it is, " { $link f } "." }
95       }
96       {
97           "state"
98           { "a " { $link string } " indicating what the thread is waiting for, or " { $link f } ". This slot is intended to be used for debugging purposes." }
99       }
100       {
101           "context"
102           { "a " { $link box } " holding an alien pointer to the threads " { $link context } " object." }
103       }
104     }
105 } ;
106
107 HELP: self
108 { $values { "thread" thread } }
109 { $description "Pushes the currently-running thread." } ;
110
111 HELP: <thread>
112 { $values { "quot" quotation } { "name" string } { "thread" thread } }
113 { $description "Low-level thread constructor. The thread runs the quotation when spawned."
114 $nl
115 "The name is used to identify the thread for debugging purposes; see " { $link "tools.threads" } "." }
116 { $notes "In most cases, user code should call " { $link spawn } " instead, however for control over the error handler quotation, threads can be created with " { $link <thread> } " then passed to " { $link (spawn) } "." } ;
117
118 HELP: run-queue
119 { $values { "dlist" dlist } }
120 { $var-description "Global variable holding the queue of runnable threads. Calls to " { $link yield } " switch to the thread which has been in the queue for the longest period of time."
121 $nl
122 "By convention, threads are queued with " { $link push-front }
123 " and dequed with " { $link pop-back } "." } ;
124
125 HELP: resume
126 { $values { "thread" thread } }
127 { $description "Adds a thread to the end of the run queue. The thread must have previously been suspended by a call to " { $link suspend } "." } ;
128
129 HELP: resume-with
130 { $values { "obj" object } { "thread" thread } }
131 { $description "Adds a thread to the end of the run queue together with an object to pass to the thread. The thread must have previously been suspended by a call to " { $link suspend } "; the object is returned from the " { $link suspend } " call." } ;
132
133 HELP: sleep-queue
134 { $values { "heap" min-heap } }
135 { $var-description "A " { $link min-heap } " storing the queue of sleeping threads." } ;
136
137 HELP: sleep-time
138 { $values { "nanos/f" { $maybe "a non-negative integer" } } }
139 { $description "Returns the time until the next sleeping thread is scheduled to wake up, which could be zero if there are threads in the run queue, or threads which need to wake up right now. If there are no runnable or sleeping threads, returns " { $link f } "." } ;
140
141 HELP: stop
142 { $description "Stops the current thread. The thread may be started again from another thread using " { $link (spawn) } "." } ;
143
144 HELP: yield
145 { $description "Adds the current thread to the end of the run queue, and switches to the next runnable thread." } ;
146
147 HELP: sleep-until
148 { $values { "n/f" { $maybe "a non-negative integer" } } }
149 { $description "Suspends the current thread until the given nanosecond count, returned by " { $link nano-count } ", is reached, or indefinitely if a value of " { $link f } " is passed in."
150 $nl
151 "Other threads may interrupt the sleep by calling " { $link interrupt } "." } ;
152
153 HELP: sleep
154 { $values { "dt" "a duration" } }
155 { $description "Suspends the current thread for the given duration."
156 $nl
157 "Other threads may interrupt the sleep by calling " { $link interrupt } "." }
158 { $examples
159     { $code "USING: threads calendar ;" "10 seconds sleep" }
160 } ;
161
162 HELP: interrupt
163 { $values { "thread" thread } }
164 { $description "Interrupts a sleeping thread." } ;
165
166 HELP: suspend
167 { $values { "state" string } { "obj" object } }
168 { $description "Suspends the current thread. Control yields to the next runnable thread and the current thread does not execute again until it is resumed, and so the caller of this word must arrange for another thread to later resume the suspended thread with a call to " { $link resume } " or " { $link resume-with } "."
169 $nl
170 "The state string is for debugging purposes; see " { $link "tools.threads" } "." } ;
171
172 HELP: spawn
173 { $values { "quot" quotation } { "name" string } { "thread" thread } }
174 { $description "Spawns a new thread. The thread begins executing the given quotation; the name is for debugging purposes. The new thread begins running immediately and the current thread is added to the end of the run queue."
175 $nl
176 "The new thread begins with an empty data stack, an empty retain stack, and an empty catch stack. The name stack is inherited from the parent thread but may be cleared with " { $link init-namestack } "." }
177 { $notes
178      "The recommended way to pass data to the new thread is to explicitly construct a quotation containing the data, for example using " { $link curry } " or " { $link compose } "."
179 }
180 { $examples
181     "A simple thread that adds two numbers:"
182     { $code "1 2 [ + . ] 2curry \"Addition thread\" spawn" }
183     "A thread that counts to 10:"
184     ! Don't use $example below: it won't pass help-lint.
185     { $code
186       "USING: math.parser threads ;"
187       "[ 10 <iota> [ number>string write nl yield ] each ] \"test\" spawn drop"
188       "10 [ yield ] times"
189       "0"
190       "1"
191       "2"
192       "3"
193       "4"
194       "5"
195       "6"
196       "7"
197       "8"
198       "9"
199     }
200 } ;
201
202 HELP: spawn-server
203 { $values { "quot" { $quotation ( -- ? ) } } { "name" string } { "thread" thread } }
204 { $description "Convenience wrapper around " { $link spawn } " which repeatedly calls the quotation in a new thread until it outputs " { $link f } "." }
205 { $examples
206     "A thread that runs forever:"
207     { $code "[ do-foo-bar t ] \"Foo bar server\" spawn-server" }
208 } ;
209
210 HELP: init-threads
211 { $description "Called during startup to initialize the threading system. This word should never be called directly." } ;
212
213 HELP: tnamespace
214 { $values { "assoc" assoc } }
215 { $description "Outputs the current thread's set of thread-local variables." } ;
216
217 HELP: tget
218 { $values { "key" object } { "value" object } }
219 { $description "Outputs the value of a thread-local variable." } ;
220
221 HELP: tset
222 { $values { "value" object } { "key" object } }
223 { $description "Sets the value of a thread-local variable." } ;
224
225 HELP: tchange
226 { $values { "key" object } { "quot" { $quotation ( ..a value -- ..b newvalue ) } } }
227 { $description "Applies the quotation to the current value of a thread-local variable, storing the result back to the same variable." } ;