/usr/share/mozart/doc/apptut/node22.html is in mozart-doc 1.4.0-8ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>17 Situated Cell-Like Objects</TITLE><LINK href="ozdoc.css" rel="stylesheet" type="text/css"></HEAD><BODY><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node21.html#chapter.counter.object"><< Prev</A></TD><TD><A href="node19.html">- Up -</A></TD></TR></TABLE><DIV id="chapter.celloid"><H1><A name="chapter.celloid">17 Situated Cell-Like Objects</A></H1><P>In this chapter, we implement <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Celloid</SPAN></CODE>s: an extension class for objects that behave essentially like cells; they have content which can be accessed (read) and assigned (written). The new challenge here is twofold: (1) during garbage collection the content of a <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Celloid</SPAN></CODE> must also be copied, (2) we must ensure that only a local <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Celloid</SPAN></CODE> can be mutated (for a non-local one, we should signal an error).</P><P>A <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Celloid</SPAN></CODE> is <EM>situated</EM>. What does <EM>situated</EM> mean? Simply that the object resides in one specific constraint store, aka a computation space. If <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Celloid</SPAN></CODE> <CODE>C</CODE> resides in space S1, and S2 is a subspace of S1 (i. e. is subordinated to S1), it is meaningful for a thread in S2 to <EM>access</EM> <CODE>C</CODE> since any constraint (therefore value) from S1 are visible in S2, but it is generally not meaningful for a thread in S2 to <EM>assign</EM> <CODE>C</CODE> since constraints (therefore values) specific to S2 are not visible from S1. Our implementation will enforce the appropriate restrictions.</P><H2><A name="label62">17.1 Celloid Class</A></H2><P>Again, we subclass <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">OZ_Extension</SPAN></CODE>. </P><DL class="anonymous"><DD class="code"><CODE>#include <SPAN class="string">"mozart.h"</SPAN> <BR> <BR><SPAN class="keyword">class</SPAN> <SPAN class="type">Celloid</SPAN> : <SPAN class="keyword">public</SPAN> <SPAN class="type">OZ_Extension</SPAN> {<BR><SPAN class="keyword">public</SPAN>:<BR> <SPAN class="type">OZ_Term</SPAN> <SPAN class="variablename">content</SPAN>;<BR> <SPAN class="functionname">Celloid</SPAN>(<SPAN class="type">OZ_Term</SPAN> <SPAN class="variablename">t</SPAN>):content(t){}<BR> <SPAN class="keyword">static</SPAN> <SPAN class="type">int</SPAN> <SPAN class="variablename">id</SPAN>;<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">int</SPAN> <SPAN class="functionname">getIdV</SPAN>() { <SPAN class="keyword">return</SPAN> id; }<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Term</SPAN> <SPAN class="functionname">typeV</SPAN>() { <SPAN class="keyword">return</SPAN> OZ_atom(<SPAN class="string">"celloid"</SPAN>); }<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Extension</SPAN>* <SPAN class="functionname">gCollectV</SPAN>();<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Extension</SPAN>* <SPAN class="functionname">sCloneV</SPAN>();<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">void</SPAN> <SPAN class="functionname">gCollectRecurseV</SPAN>();<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">void</SPAN> <SPAN class="functionname">sCloneRecurseV</SPAN>();<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Term</SPAN> <SPAN class="functionname">printV</SPAN>(<SPAN class="type">int</SPAN> <SPAN class="variablename">depth</SPAN> = 10);<BR>};</CODE></DD></DL><P></P><H2><A name="label63">17.2 Celloid Creation</A></H2><P>The <CODE>celloid_new</CODE> builtin takes one input argument <CODE>t</CODE>, creates a new celloid whose content is initialized to <CODE>t</CODE>, boxes it and returns the result. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(celloid_new,1,1)<BR>{<BR> OZ_declareTerm(0,t);<BR> OZ_RETURN(OZ_extension(<SPAN class="keyword">new</SPAN> <SPAN class="type">Celloid</SPAN>(t)));<BR>}<BR>OZ_BI_end</CODE></DD></DL><P></P><H2><A name="label64">17.3 Type Testing</A></H2><P>The definitions here are similar to the ones presented earlier for the <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> class. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">int</SPAN> <SPAN class="reference">Celloid</SPAN>::<SPAN class="variablename">id</SPAN>;<BR> <BR><SPAN class="keyword">inline</SPAN> <SPAN class="type">OZ_Boolean</SPAN> <SPAN class="functionname">OZ_isCelloid</SPAN>(<SPAN class="type">OZ_Term</SPAN> <SPAN class="variablename">t</SPAN>)<BR>{<BR> t = OZ_deref(t);<BR> <SPAN class="keyword">return</SPAN> OZ_isExtension(t) &&<BR> OZ_getExtension(t)->getIdV()==<SPAN class="reference">Celloid</SPAN>::id;<BR>}<BR> <BR><SPAN class="functionname">OZ_BI_define</SPAN>(celloid_is,1,1)<BR>{<BR> OZ_declareDetTerm(0,t);<BR> OZ_RETURN_BOOL(OZ_isCelloid(t));<BR>}<BR>OZ_BI_end</CODE></DD></DL><P></P><H2><A name="label65">17.4 Expecting Celloid Arguments in Builtins</A></H2><P>Again this is similar to the <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> class: we define an unboxing function and a convenience macro. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="keyword">inline</SPAN> <SPAN class="type">Celloid</SPAN>* <SPAN class="functionname">OZ_CelloidToC</SPAN>(<SPAN class="type">OZ_Term</SPAN> <SPAN class="variablename">t</SPAN>)<BR>{<BR> <SPAN class="keyword">return</SPAN> (<SPAN class="type">Celloid</SPAN>*) OZ_getExtension(OZ_deref(t));<BR>}<BR> <BR>#define <SPAN class="functionname">OZ_declareCelloid</SPAN>(<SPAN class="variablename">ARG</SPAN>,<SPAN class="variablename">VAR</SPAN>) \<BR>OZ_declareType(ARG,VAR,<SPAN class="type">Celloid</SPAN>*,<SPAN class="string">"celloid"</SPAN>,OZ_isCelloid,OZ_CelloidToC)</CODE></DD></DL><P></P><H2><A name="label66">17.5 Operations on Celloids</A></H2><P>First, we provide an <EM>access</EM> builtin that retrieves the content of the celloid. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(celloid_access,1,1)<BR>{<BR> OZ_declareCelloid(0,c);<BR> OZ_RETURN(c->content);<BR>}<BR>OZ_BI_end</CODE></DD></DL><P> Second, we provide an <EM>assign</EM> builtin that sets the content of the celloid. This operation should only be allowed for a thread executing in the home space of the celloid. For a thread executing in a subordinated space, an exception will be raised. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(celloid_assign,2,0)<BR>{<BR> OZ_declareCelloid(0,c);<BR> OZ_declareTerm(1,t);<BR> <SPAN class="keyword">if</SPAN> (c->isLocal()) { c->content=t; <SPAN class="keyword">return</SPAN> PROCEED; }<BR> <SPAN class="keyword">else</SPAN> <SPAN class="keyword">return</SPAN> OZ_raiseErrorC(<SPAN class="string">"celloid"</SPAN>,3,OZ_atom(<SPAN class="string">"nonLocal"</SPAN>),<BR> OZ_in(0),OZ_in(1));<BR>}<BR>OZ_BI_end</CODE></DD></DL><P> virtual member function <CODE>isLocal()</CODE> indicates whether the current space is the home space of the celloid. If yes, we set the content to the given argument; if no, we raise an error. <CODE>OZ_in(</CODE><I>n</I><CODE>)</CODE> refers to the <I>n</I>th input argument of the builtin.</P><H2><A name="label67">17.6 Printing Support</A></H2><P>We provide here only minimal printing support. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_Term</SPAN> <SPAN class="reference">Celloid</SPAN>::<SPAN class="functionname">printV</SPAN>(<SPAN class="type">int</SPAN> <SPAN class="variablename">depth</SPAN> = 10)<BR>{<BR> <SPAN class="keyword">return</SPAN> OZ_atom(<SPAN class="string">"<celloid>"</SPAN>);<BR>}</CODE></DD></DL><P></P><H2><A name="label68">17.7 Garbage Collection</A></H2><P>The first part of garbage collection is as before: we create a new instance of <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Celloid</SPAN></CODE> initialized with the current content of the celloid that is being copied by gc. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_Extension</SPAN>* <SPAN class="reference">Celloid</SPAN>::<SPAN class="functionname">gCollectV</SPAN>() { <SPAN class="keyword">return</SPAN> <SPAN class="keyword">new</SPAN> <SPAN class="type">Celloid</SPAN>(content); }</CODE></DD></DL><P> The second part involves recursively copying the content of the celloid. This is implemented in a different virtual function: </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">void</SPAN> <SPAN class="reference">Celloid</SPAN>::<SPAN class="functionname">gCollectRecurseV</SPAN>() { OZ_gCollect(&content); }</CODE></DD></DL><P> The procedure <CODE>OZ_gCollect(<SPAN class="type">OZ_Term</SPAN>*)</CODE> performs the gc copy and update of its argument.</P><P>You may wonder: why not perform the recursive copy of the content in <CODE>gCollectV()</CODE> itself. Under no circumstances should you do this! It would break essential invariants in the garbage collector. GC copy must proceed in these 2 phases: </P><OL type="1"><LI><P><CODE>gCollectV()</CODE> creates a new instance (on the <EM>to</EM> heap) and initializes it with the current contents of the object being gced. </P></LI><LI><P><CODE>gCollectRecurseV()</CODE> is at some subsequent point invoked on the new instance and should perform the gc copy and update of its contents.</P></LI></OL><P></P><H2><A name="label69">17.8 Cloning</A></H2><P>Cloning is used to produce a copy of a computation space. It has the same structure, and the underlying implementation in fact shares most of the code with, garbage collection. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_Extension</SPAN>* <SPAN class="reference">Celloid</SPAN>::<SPAN class="functionname">sCloneV</SPAN>() { <SPAN class="keyword">return</SPAN> <SPAN class="keyword">new</SPAN> <SPAN class="type">Celloid</SPAN>(content); }<BR><SPAN class="type">void</SPAN> <SPAN class="reference">Celloid</SPAN>::<SPAN class="functionname">sCloneRecurseV</SPAN>() { OZ_sClone(&content); }</CODE></DD></DL><P> </P><H2><A name="label70">17.9 Native Functor</A></H2><P>Again, we proceed as before: </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_C_proc_interface</SPAN> * <SPAN class="functionname">oz_init_module</SPAN>(<SPAN class="type">void</SPAN>)<BR>{<BR> <SPAN class="keyword">static</SPAN> <SPAN class="type">OZ_C_proc_interface</SPAN> <SPAN class="variablename">table</SPAN>[] = {<BR> {<SPAN class="string">"new"</SPAN>,1,1,celloid_new},<BR> {<SPAN class="string">"is"</SPAN>,1,1,celloid_is},<BR> {<SPAN class="string">"access"</SPAN>,1,1,celloid_access},<BR> {<SPAN class="string">"assign"</SPAN>,2,0,celloid_assign},<BR> {0,0,0,0}<BR> };<BR> <SPAN class="reference">Celloid</SPAN>::id = OZ_getUniqueId();<BR> <SPAN class="keyword">return</SPAN> table;<BR>}</CODE></DD></DL><P> Assuming the code above is put in file <A href="celloid.cc"><CODE>celloid.cc</CODE></A>, we first compile and then create a DLL as follows </P><BLOCKQUOTE class="code"><CODE>oztool c++ -c celloid.cc<BR>oztool ld celloid.o -o celloid.so-`oztool platform`</CODE></BLOCKQUOTE><P></P><H2><A name="label71">17.10 Oz Wrapper Module</A></H2><P>Here, we hardly need an Oz wrapper module. Unlike for counter objects, we don't need to register celloid for finalization: there are no resources off the heap. However, we can provide a nice error print formatter for the case when an access is attempted from without the celloid's home space. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="keyword">functor</SPAN> <BR><SPAN class="keyword">import</SPAN> <BR> Celloid(new:New is:Is access:Access assign:Assign)<BR> <SPAN class="keyword">at</SPAN> <SPAN class="string">'celloid.so{native}'</SPAN> <BR> Error(registerFormatter)<BR><SPAN class="keyword">export</SPAN> <BR> New Is Access Assign<BR><SPAN class="keyword">define</SPAN> <BR> <SPAN class="keyword">fun</SPAN><SPAN class="variablename"> </SPAN>{<SPAN class="functionname">CelloidFormatter</SPAN> E}<BR> T = <SPAN class="string">'Celloid Error'</SPAN> <BR> <SPAN class="keyword">in</SPAN> <BR> <SPAN class="keyword">case</SPAN> E <SPAN class="keyword">of</SPAN> celloid(nonLocal C V) <SPAN class="keyword">then</SPAN> <BR> error(kind: T<BR> msg: <SPAN class="string">'Attempted assign on non local celloid'</SPAN> <BR> items: [hint(l:<SPAN class="string">'Operation'</SPAN> m:<SPAN class="string">'Celloid.assign'</SPAN>)<BR> hint(l:<SPAN class="string">'Celloid'</SPAN> m:oz(C))<BR> hint(l:<SPAN class="string">'Value'</SPAN> m:oz(V))])<BR> <SPAN class="keyword">else</SPAN> <BR> error(kind: T<BR> items: [line(oz(E))])<BR> <SPAN class="keyword">end</SPAN> <BR> <SPAN class="keyword">end</SPAN> <BR> {Error<SPAN class="keyword">.</SPAN>registerFormatter celloid CelloidFormatter}<BR><SPAN class="keyword">end</SPAN></CODE></DD></DL><P></P></DIV><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node21.html#chapter.counter.object"><< Prev</A></TD><TD><A href="node19.html">- Up -</A></TD></TR></TABLE><HR><ADDRESS><A href="http://www.ps.uni-sb.de/~duchier/">Denys Duchier</A>, <A href="http://www.ps.uni-sb.de/~kornstae/">Leif Kornstaedt</A> and <A href="http://www.ps.uni-sb.de/~schulte/">Christian Schulte</A><BR><SPAN class="version">Version 1.4.0 (20110908185330)</SPAN></ADDRESS></BODY></HTML>
|