]> gitweb.factorcode.org Git - factor.git/blob - basis/concurrency/semaphores/semaphores-docs.factor
06c951f58651ca6fb1382b7dba6131b3506a4c61
[factor.git] / basis / concurrency / semaphores / semaphores-docs.factor
1 IN: concurrency.semaphores\r
2 USING: help.markup help.syntax kernel quotations calendar ;\r
3 \r
4 HELP: semaphore\r
5 { $class-description "The class of counting semaphores. New instances can be created by calling " { $link <semaphore> } "." } ;\r
6 \r
7 HELP: <semaphore>\r
8 { $values { "n" "a non-negative integer" } { "semaphore" semaphore } }\r
9 { $description "Creates a counting semaphore with the specified initial count." } ;\r
10 \r
11 HELP: acquire-timeout\r
12 { $values { "semaphore" semaphore } { "timeout" { $maybe duration } } }\r
13 { $description "If the semaphore has a non-zero count, decrements it and returns immediately. Otherwise, if the timeout is " { $link f } ", waits indefinitely for the semaphore to be released. If the timeout is not " { $link f } ", waits a certain period of time, and if the semaphore still has not been released, throws an error." }\r
14 { $errors "Throws an error if the timeout expires before the semaphore is released." } ;\r
15 \r
16 HELP: acquire\r
17 { $values { "semaphore" semaphore } }\r
18 { $description "If the semaphore has a non-zero count, decrements it and returns immediately. Otherwise, waits for it to be released." } ;\r
19 \r
20 HELP: release\r
21 { $values { "semaphore" semaphore } }\r
22 { $description "Increments a semaphore's count. If the count was previously zero, any threads waiting on the semaphore are woken up." } ;\r
23 \r
24 HELP: with-semaphore-timeout\r
25 { $values { "semaphore" semaphore } { "timeout" { $maybe duration } } { "quot" quotation } }\r
26 { $description "Calls the quotation with the semaphore held." } ;\r
27 \r
28 HELP: with-semaphore\r
29 { $values { "semaphore" semaphore } { "quot" quotation } }\r
30 { $description "Calls the quotation with the semaphore held." } ;\r
31 \r
32 ARTICLE: "concurrency.semaphores.examples" "Semaphore examples"\r
33 "A use-case would be a batch processing server which runs a large number of jobs which perform calculations but then need to fire off expensive external processes or perform heavy network I/O. While for most of the time, the threads can all run in parallel, it might be desired that the expensive operation is not run by more than 10 threads at once, to avoid thrashing swap space or saturating the network. This can be accomplished with a counting semaphore:"\r
34 { $code\r
35     "SYMBOL: expensive-section"\r
36     "requests"\r
37     "10 <semaphore> '["\r
38     "    ..."\r
39     "    _ [ do-expensive-stuff ] with-semaphore"\r
40     "    ..."\r
41     "] parallel-map"\r
42 }\r
43 "Here is a concrete example which fetches content from 5 different web sites, making no more than 3 requests at a time:"\r
44 { $code\r
45     """USING: concurrency.combinators concurrency.semaphores\r
46 fry http.client kernel urls ;\r
47 \r
48 {\r
49     URL" http://www.apple.com"\r
50     URL" http://www.google.com"\r
51     URL" http://www.ibm.com"\r
52     URL" http://www.hp.com"\r
53     URL" http://www.oracle.com"\r
54 }\r
55 2 <semaphore> '[\r
56     _ [ http-get nip ] with-semaphore\r
57 ] parallel-map"""\r
58 } ;\r
59 \r
60 ARTICLE: "concurrency.semaphores" "Counting semaphores"\r
61 "Counting semaphores are used to ensure that no more than a fixed number of threads are executing in a critical section at a time; as such, they generalize " { $vocab-link "concurrency.locks" } ", since locks can be thought of as semaphores with an initial count of 1."\r
62 { $subsections "concurrency.semaphores.examples" }\r
63 "Creating semaphores:"\r
64 { $subsections\r
65     semaphore\r
66     <semaphore>\r
67 }\r
68 "Unlike locks, where acquisition and release are always paired by a combinator, semaphores expose these operations directly and there is no requirement that they be performed in the same thread:"\r
69 { $subsections\r
70     acquire\r
71     acquire-timeout\r
72     release\r
73 }\r
74 "Combinators which pair acquisition and release:"\r
75 { $subsections\r
76     with-semaphore\r
77     with-semaphore-timeout\r
78 } ;\r
79 \r
80 ABOUT: "concurrency.semaphores"\r