Reading the value of a variable and the result of a function
Turtles in POOL are active objects composed of member variables, properties and functions. Each turtle-object
has its own queue of tasks (a thread). If a turtle's member function is called by another turtle, it is executed
in parallel to the code that has called the function. Functions called in this way are treated as tasks and queued
in the order as they were called. All instructions that are affecting a turtle's state are also treated as tasks
if called by remote turtle, e.g. forward,
setpencolor
.
Execution of a turtle program is suspended on the first attempt of reading the result of task of another turtle
if that result is not yet ready (see examples 1, 2).
In contrast to function calls, reading values of a remote turtle's variables and properies is done within
the task of a turtle that is requesting the read operation. No parallel task is created and the result is available
immediately. This allows for monitoring of variables and properties of a remote turtle (e.g. pos,
pencolor
) ), even if that turtle is performing a long-lasting task (see
example 3).
In order to synchronize the read operations with a remote turtle tasks, define getter functions like:
to model
"x := 5
to getx op :x end
to getpos op pos end
end
Example 1:
The program stores outputs from the factorial
function in the :y
array. Since the items from the array are used only by print :y
command, it is possible to run the entire for
loop and launch the
parallel calculations for each function call within the loop.
to factorial :x
(print who :x)
if :x > 1 [op :x * factorial :x - 1]
op 1
end
"n := 3
"y := newarray :n
"t := (anewturtles :n)
for [i 1 :n] [:y,:i := (factorial :i+2) @ :t,:i]
print :y
Output:
The order of text lines appearing in the output may differ for each run, except the result "{6 24 120}", which
always comes at the end.
t1 3
t2 4
t3 5
t1 2
t2 3
t3 4
t1 1
t2 2
t3 3
t2 1
t3 2
t3 1
{6 24 120}
Example 2:
The program stores the output from fn
function in the :p
variable. Since this result is used only in the last command in the code, it is possible to complete earlier
commands before the long-lasting function is finished.
to model :param
to fn :x
(print "start "fn :x)
wait 2000
let "result :x * :param
print "|result ready|
op :result
end
end
"t := (newt $model 2)
print "|call fn|
"p := (fn 5) @ :t
repeat 3 [wait 200 (print "|parallel code| repcount)]
print "wait...
(print "use :p)
Output:
call fn
start fn 5
parallel code 1
parallel code 2
parallel code 3
wait...
result ready
use 10
Example 3:
The vary_q
function is time consuming. Value of the :q
variable is changing during the function execution. The program is monitoring these changes in parallel to the
function execution.
to model :param
to vary_q
repeat 3 [
wait 200
"q += 1
wait 200
]
"stop := true
end
"stop := false
"q := :param
end
"t := (newt $model 0)
"test := :q @ :t
vary_q @ :t
while not :stop @ :t [
"n := :q @ :t
if :test <> :n ["test := :n (print "change :n repcount)]
wait 10
]
print "stop
Output:
change 1 22
change 2 61
change 3 101
stop
See also:
Local, global and shared variables
Classes and inheritance
@ (access to class members)
Table of Content