Skip to content

Commit cadea23

Browse files
author
Alex Razoumov
committed
explain the example with writeEF/readFF in more detail; change the discussion with an example that will block for sure, and provide the solution/explanation of why it blocks
1 parent cbd7f25 commit cadea23

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

episodes/13-synchronization.md

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -148,17 +148,26 @@ To assign a new value to a _sync_ variable, its state must be _empty_ (after the
148148
completed, the state will be set as _full_). On the contrary, to read a value from a _sync_ variable, its
149149
state must be _full_ (after the read operation is completed, the state will be set as _empty_ again).
150150

151+
Starting from Chapel 2.x, you must use functions `writeEF` and `readFF` to perform blocking write and read
152+
with sync variables. Below is an example to demonstrate the use of sync variables. Here we launch a new task
153+
that is busy for a short time executing the loop. While this loop is running, the main task continues printing
154+
the message "this is main task after launching new task... I will wait until it is done". As it takes time to
155+
spawn a new thread, it is very likely that you will see this message before the output from the loop. Next,
156+
the main task will attempt to read `x` and assign it to `a` which it can only do when `x` is full. We write
157+
into `x` after the loop, so you will see the final message "and now it is done" only after the message "New
158+
task finished". In other words, reading `x`, we pause the execution of the main thread.
159+
151160
```chpl
152161
var x: sync int, a: int;
153162
writeln("this is main task launching a new task");
154163
begin {
155164
for i in 1..10 do writeln("this is new task working: ",i);
156-
x.writeEF(2);
165+
x.writeEF(2); // assign 2 to x
157166
writeln("New task finished");
158167
}
159168
160-
writeln("this is main task after launching new task... I will wait until it is done");
161-
a = x.readFF(); // don't run this line until the variable x is written in the other task
169+
writeln("this is main task after launching new task... I will wait until it is done");
170+
a = x.readFE(); // don't run this line until the variable x is written in the other task
162171
writeln("and now it is done");
163172
```
164173

@@ -169,7 +178,7 @@ chpl sync_example_2.chpl
169178

170179
```output
171180
this is main task launching a new task
172-
this is main task after launching new task... I will wait until it is done
181+
this is main task after launching new task... I will wait until it is done
173182
this is new task working: 1
174183
this is new task working: 2
175184
this is new task working: 3
@@ -188,21 +197,28 @@ and now it is done
188197

189198
## Discussion
190199

191-
What would happen if we assign a value to _x_ right before launching the new task? What would happen if we
192-
assign a value to _x_ right before launching the new task and after the _writeln("and now it is done");_
193-
statement?
194-
195-
Discuss your observations.
196-
197-
198-
199-
abc
200-
201-
202-
200+
What would happen if we try to read `x` inside the new task as well, i.e. we have the following `begin`
201+
statement, without changing the rest of the code:
203202

203+
```chpl
204+
begin {
205+
for i in 1..10 do writeln("this is new task working: ",i);
206+
x.writeEF(2);
207+
writeln("New task finished");
208+
x.readFE();
209+
}
210+
```
211+
:::::::::::::::::::::::: solution
204212

213+
The code will block (run forever), and you would need to press *Ctrl-C* to halt its execution. In this example
214+
we try to read `x` in two places: the main task and the new task. When we read a sync variable with `readFE`,
215+
the state of the sync variable is set to empty when this method completes. In other words, one of the two
216+
`readFE` calls will succeed (which one -- depends on the runtime) and will mark the variable as empty. The
217+
other `readFE` will then attempt to read it but it will block waiting for `x` to become full again (which will
218+
never happen). In the end, the execution of either the main thread or the child thread will block, hanging the
219+
entire code.
205220

221+
:::::::::::::::::::::::::::::::::
206222
:::::::::::::::::::::::::::::::::::::::::::::::::::
207223

208224
There are a number of methods defined for _sync_ variables. Suppose _x_ is a sync variable of a given type,

0 commit comments

Comments
 (0)