Render
modulesThe iterator on scenes in defined in the Scene
module.
For simplicity we present iteration by the line.
The master uses the fold pool of section 4.2,
of which register
function is stored in the local name service.
As specified by the type constraint above, remote workers return pairs of a line number and of a line of pixels.
Finally, the following function commands the rendering of scene sc
and saves the resulting image.
Notice that the combination function performs an update of
the bitmap img
.
It should be noticed that render_image
above returns only when the
image is saved. We can then define RenderMaster.render
as being
render_image
.
As a consequence, all images are saved when the interpreter terminates and the master can terminate.
In our implementation, we in fact save the image asynchronously, for disk operations not to delay the interpreter. Termination of the master is then controlled by a simple monitor (page ??) that counts images.
The monitor is made public by the module RenderMaster
,
for the code after the call to the interpreter to wait on it.
A slave executes two tasks concurrently. It (1) interprets the Gml program so as to build the scenes and (2) computes subimages on master demand. For the two agents to communicate, we introduce a suitable mapping from filenames to scenes.
The code above is a wrapper of the (OCaml) hashtable t
.
There are two points to notice.
First, by very existence of state
the internal hashtable t
is protected against concurrent modification, as usual.
Second, the synchronous channel find
blocks
when the table t
does not associate any value to the
key k
, until a value for k
is added into the table.
This block/release process implies a form of communication
between find and add operations.
Such a communication is by the means of the message that is pending over
the internal channel state
.
More precisely, the code of find
first changes the interface to Hashtbl.find
“return
value v
or raise exception Not_found
” into the new interface
“return Some v
or return None
”.
In the first, successful, case the caller of find
gets v
as a reply.
In the second, failed, case the reply to find
is delayed, by inserting a call wait()
before
calling find
again.
The call to wait
will return when a message is sent on the asynchronous
channel release
, which the code for add
does.
A find operation is then attempted again.
The coding is slightly inefficient, but it suffices here.
Namely, the pool of the master does not allow several concurrent
calls to find
in a given slave. Thus the list blocked
cannot
hold more than one element.
Actual subimage computations are performed by the following definition.
Additionally, compute_subimage
is registered into the pool of
the master, we omit the code which is the same as the one of
section 4.3.
Finally, RenderSlave.render
simply stores the scene
at the intention of compute_subimage
.
As regards termination, the simplest solution is for slaves to terminate when the master does — see the end of section 4.3.