]> gitweb.factorcode.org Git - factor.git/blob - basis/concurrency/semaphores/semaphores-docs.factor
379fd6a3a0b5c37e667687d973ab780faf120b5d
[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." } ;\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" "a " { $link duration } " or " { $link f } } }\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" "a " { $link duration } " or " { $link f } } { "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" "Counting semaphores"\r
33 "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
34 $nl\r
35 "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
36 { $code\r
37     "SYMBOL: expensive-section"\r
38     "10 <semaphore> expensive-section set-global"\r
39     "requests ["\r
40     "    ..."\r
41     "    expensive-section [ do-expensive-stuff ] with-semaphore"\r
42     "    ..."\r
43     "] parallel-map"\r
44 }\r
45 "Creating semaphores:"\r
46 { $subsection semaphore }\r
47 { $subsection <semaphore> }\r
48 "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
49 { $subsection acquire }\r
50 { $subsection acquire-timeout }\r
51 { $subsection release }\r
52 "Combinators which pair acquisition and release:"\r
53 { $subsection with-semaphore }\r
54 { $subsection with-semaphore-timeout } ;\r
55 \r
56 ABOUT: "concurrency.semaphores"\r