QcPenPrinter: no need to allocate QPrintDialog on heap
[supercollider.git] / HelpSource / Classes / Semaphore.schelp
blob79606af8d926a2fc5c8bdb5937a0b0a12b030ace
1 CLASS::Semaphore
2 categories::Scheduling
3 summary::control parallel execution of threads
5 CLASSMETHODS::
7 method::new
8 Create a new instance, set the maximum number of running threads (default: 1).
10 INSTANCEMETHODS::
12 method::count
13 Determines the number of running threads.
15 method::clear
16 Remove any reference to threads, but do not reschedule any pending ones.
18 method::wait
19 Stop current thread if already too many are running, otherwise continue.
21 method::signal
22 Unblock the semaphore, reschedule next pending thread.
24 EXAMPLES::
26 code::
27 // allow only one thread
29 c = Semaphore(1);
30 fork {
31         c.wait;
32         "thread 1> now I am doing something for 10 seconds. Block the semaphore meanwhile.".postln;
33         10.wait;
34         c.signal;
35         "thread 1> ok, done. Release the semaphore.".postln;
37 fork {
38         3.0.rand.wait;
39         "thread 2> I would like to go on, if I may.".postln;
40         c.wait; // may I?
41         "thread 2> this took until the other thread has released the semaphore. "
42                 "Blocking for 4 seconds.".postln;
43         4.wait;
44         "thread 2> ok, done. Releasing the semaphore".postln;
45         c.signal;
47 fork {
48         4.wait;
49         "thread 3> I, too, would like to go on, if I may.".postln;
50         c.wait; // may I?
51         "thread 3> this took until both other threads had released the semaphore.".postln;
52         c.signal;
57 code::
58 // allow two threads at a time.
60 c = Semaphore(2);
61 fork {
62         c.wait;
63         "thread 1> now I am doing something for 20 seconds. Block the semaphore.".postln;
64         10.wait;
65         "thread 1> ok, done. Releasing the semaphore".postln;
66         c.signal;
68 fork {
69         rrand(3.0, 5.0).wait;
70         "thread 2> I would like to go on, if I may.".postln;
71         if(c.count <= 0) { "thread 3> ok, then I wait ...".postln };
72         c.wait; // may I?
73         "thread 1> ok, going ahead.".postln;
74         17.wait;
75         "thread 2> ok, done. Releasing the semaphore".postln;
76         c.signal;
78 fork {
79         6.wait;
80         "thread 3> I, too, would like to go on, if I may.".postln;
81         if(c.count <= 0) { "thread 3> ok, then I wait ...".postln };
82         c.wait; // may I?
83         "thread 3> ok, this took until the first thread had released the semaphore. "
84                 "Ok, doing something for 4 seconds. Block the semaphore".postln;
85                 4.wait;
86         "Releasing the semaphore.".postln;
87         c.signal;
89 fork {
90         7.wait;
91         "thread 4> Me, the fourth one, would like to go on, if I may.".postln;
92         if(c.count <= 0) { "thread 4> ok, then I wait ...".postln };
93         c.wait; // may I?
94         "thread 4> ok, this took until the third thread had released the semaphore. "
95                 "Ok, doing something for 3 seconds. Block the semaphore".postln;
96                 3.wait;
97         "Releasing the semaphore.".postln;
98         c.signal;
103 code::
104 // grant exclusive access to data to only one thread
105 // there should never be mixed values in the data array
107 var data, useAndModify;
109 data = [1, 2, 3];
110 c = Semaphore(1);
111 // c = Semaphore(2); use this to test how it would behave without exclusive access.
112 useAndModify = { |newData, who|
113         postln(who + "trying to get blocking access.");
114         if(c.count <= 0) { who + "ok, then I wait ...".postln };
115         c.wait; // may I access? if not, I wait. if yes, disallow others.
116         "\n".post;
117         (who + "continuing...").postln;
118         data.do({ |x|
119                         0.1.wait;
120                         postln(who + x);
121                 });
122         "\n".post;
123         newData.do { |x, i| data[i] = x };
124         postln(who + "rewriting data to:" + newData);
125         postln(who + "releasing");
126         c.signal; // allow others access again
129 // e.g. set the values to integers
130 u = Routine {
131         inf.do { |i|
132                 useAndModify.value([100, 200, 300], "thread 1>");
133                 rrand(1, 3).wait;
134         }
137 // e.g. set the values to floats
138 k =  Routine {
139         0.5.wait;
140         inf.do { |i|
141                 useAndModify.value([pi, 0.5pi, 2pi], "thread 2>");
142                 rrand(1, 5).wait;
143         }
145 u.play;
146 k.play;