/usr/share/mozart/doc/apptut/node21.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>16 Native Counter 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="node20.html#chapter.counter.global"><< Prev</A></TD><TD><A href="node19.html">- Up -</A></TD><TD><A href="node22.html#chapter.celloid">Next >></A></TD></TR></TABLE><DIV id="chapter.counter.object"><H1><A name="chapter.counter.object">16 Native Counter Objects</A></H1><P>In this chapter, we are going to generalize the counter idea: instead of having just one global counter, we are going to have counter objects implemented as extensions. Of course, this is intended purely as a didactic exercise: such counters could much more easily be defined as Oz objects directly.</P><H2><A name="label53">16.1 Counter Class</A></H2><P>We derive a new <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> class from the base class <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">Counter</SPAN> : <SPAN class="keyword">public</SPAN> <SPAN class="type">OZ_Extension</SPAN> {<BR><SPAN class="keyword">public</SPAN>:<BR> <SPAN class="type">long</SPAN> * <SPAN class="variablename">n</SPAN>;<BR> <SPAN class="functionname">Counter</SPAN>();<BR> <SPAN class="functionname">Counter</SPAN>(<SPAN class="type">long</SPAN>*);<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>();<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Term</SPAN> <SPAN class="functionname">typeV</SPAN>();<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Extension</SPAN>* <SPAN class="functionname">gCollectV</SPAN>(<SPAN class="type">void</SPAN>);<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">OZ_Extension</SPAN>* <SPAN class="functionname">sCloneV</SPAN>(<SPAN class="type">void</SPAN>);<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">void</SPAN> <SPAN class="functionname">gCollectRecurseV</SPAN>(<SPAN class="type">void</SPAN>) {}<BR> <SPAN class="keyword">virtual</SPAN> <SPAN class="type">void</SPAN> <SPAN class="functionname">sCloneRecurseV</SPAN>(<SPAN class="type">void</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> A <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> object contains a pointer to a malloced <CODE><SPAN class="type">long</SPAN></CODE>. Why not simply have a member of type <CODE><SPAN class="type">long</SPAN></CODE>: simply because we want to illustrate an application of finalization; malloced memory is a resource that needs to be freed when no longer needed.</P><P>The <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> class provides implementations for a number of virtual member functions introduced by class <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Oz_Extension</SPAN></CODE>. We are now going to explain each of them and provide the necessary code.</P><H2><A name="label54">16.2 Counter Creation</A></H2><P>For this we need the <CODE>Counter()</CODE> constructor and the new builtin <CODE>counter_new</CODE>. The constructor allocates a new <CODE><SPAN class="type">long</SPAN></CODE>, sets <CODE>n</CODE> to its address and initializes it with 1. The builtin creates a new instance of the <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> class, boxes it as an Oz value by invoking <CODE>OZ_extension</CODE> and returns the result. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">Counter</SPAN>() { n = <SPAN class="keyword">new</SPAN> <SPAN class="type">long</SPAN>[1]; n[0]=1; }<BR> <BR><SPAN class="functionname">OZ_BI_define</SPAN>(counter_new,0,1)<BR>{<BR> OZ_RETURN(OZ_extension(<SPAN class="keyword">new</SPAN> <SPAN class="type">Counter</SPAN>));<BR>}<BR>OZ_BI_end</CODE></DD></DL><P></P><H2><A name="label55">16.3 Type Testing</A></H2><P>Every extension class should be uniquely identified. This is the purpose of virtual function <CODE>getIdV</CODE>. Here we illustrate the usual way of doing so: the class is equipped with a static <CODE>id</CODE> member and <CODE>getIdV()</CODE> returns it. This static member is initialized by <CODE>oz_init_module()</CODE> (see <A href="node21.html#section.counter.object.functor">Section 16.9</A>). </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">int</SPAN> <SPAN class="reference">Counter</SPAN>::<SPAN class="variablename">id</SPAN>;<BR><SPAN class="type">int</SPAN> <SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">getIdV</SPAN>() { <SPAN class="keyword">return</SPAN> id; }</CODE></DD></DL><P> Your code will also need to test whether some <CODE>OZ_Term</CODE> is in fact a boxed <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE>. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="keyword">inline</SPAN> <SPAN class="type">OZ_Boolean</SPAN> <SPAN class="functionname">OZ_isCounter</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">Counter</SPAN>::id;<BR>}</CODE></DD></DL><P> Additionally, you should probably provide a builtin to perform this test in Oz code: </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(counter_is,1,1)<BR>{<BR> OZ_declareDetTerm(0,t);<BR> OZ_RETURN_BOOL(OZ_isCounter(t));<BR>}<BR>OZ_BI_end</CODE></DD></DL><P> Finally, it would be nice if <CODE>{Value<SPAN class="keyword">.</SPAN>type C}</CODE> would return the atom <CODE>counter</CODE> when <CODE>C</CODE> is a counter object. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_Term</SPAN> <SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">typeV</SPAN>() { <SPAN class="keyword">return</SPAN> OZ_atom(<SPAN class="string">"counter"</SPAN>); } </CODE></DD></DL><P></P><H2><A name="label56">16.4 Expecting Counter Arguments in Builtins</A></H2><P>Obviously we need a way to unbox counter objects. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="keyword">inline</SPAN> <SPAN class="type">Counter</SPAN>* <SPAN class="functionname">OZ_CounterToC</SPAN>(<SPAN class="type">OZ_Term</SPAN> <SPAN class="variablename">t</SPAN>)<BR>{<BR> <SPAN class="keyword">return</SPAN> (<SPAN class="type">Counter</SPAN>*) OZ_getExtension(OZ_deref(t));<BR>}</CODE></DD></DL><P> Now we can define a convenient macro that we can use in the implementation of a builtin to wait until argument <CODE>ARG</CODE> is determined, check that it is a boxed <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE>, and declare a variable <CODE>VAR</CODE> to hold a pointer to its unboxed value. </P><DL class="anonymous"><DD class="code"><CODE>#define <SPAN class="functionname">OZ_declareCounter</SPAN>(<SPAN class="variablename">ARG</SPAN>,<SPAN class="variablename">VAR</SPAN>) \<BR>OZ_declareType(ARG,VAR,<SPAN class="type">Counter</SPAN>*,<SPAN class="string">"counter"</SPAN>,OZ_isCounter,OZ_CounterToC)</CODE></DD></DL><P> Next, we illustrate how to use this macro.</P><H2><A name="label57">16.5 Operations on Counters</A></H2><P>The first operation obtains the current value of the counter object, but does not change it. We use our new macro to state that the first argument (i. e. argument number 0) should be a determined boxed counter and that <CODE>c</CODE> should be set to point to its unboxed value. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(counter_get,1,1)<BR>{<BR> OZ_declareCounter(0,c);<BR> OZ_RETURN_INT(*c->n);<BR>}<BR>OZ_BI_end</CODE></DD></DL><P> Thanks to our macro, if the argument is not determined, the builtin will automatically suspend, and if it is determined but is not a counter object, it will raise an error exception.</P><P>We can similarly define a builtin for setting the value of the counter. It takes 2 arguments: a counter object and an integer. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(counter_set,2,0)<BR>{<BR> OZ_declareCounter(0,c);<BR> OZ_declareInt(1,i);<BR> *c->n=i;<BR> <SPAN class="keyword">return</SPAN> PROCEED;<BR>}<BR>OZ_BI_end</CODE></DD></DL><P></P><P>Finally, we can define a builtin to obtain the current value of a counter object and post increment the counter by 1. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(counter_next,1,1)<BR>{<BR> OZ_declareCounter(0,c);<BR> <SPAN class="type">long</SPAN> <SPAN class="variablename">i</SPAN> = *c->n;<BR> *c->n = i+1;<BR> OZ_RETURN_INT(i);<BR>}<BR>OZ_BI_end</CODE></DD></DL><P></P><H2><A name="label58">16.6 Printing Support</A></H2><P>Of course, it would be nice if <CODE>{<SPAN class="type">Show</SPAN> <SPAN class="variablename">C</SPAN>}</CODE>, when <CODE>C</CODE> is a counter object, would display <CODE><counter </CODE><I>n</I><CODE>></CODE> where <I>n</I> is the current value of the counter. This is easily achieved by defining virtual function <CODE>printV</CODE> to return an appropriate virtual string. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_Term</SPAN> <SPAN class="reference">Counter</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_mkTupleC(<SPAN class="string">"#"</SPAN>,3,<BR> OZ_atom(<SPAN class="string">"<counter "</SPAN>),<BR> OZ_int(*n),<BR> OZ_atom(<SPAN class="string">">"</SPAN>));<BR>}</CODE></DD></DL><P></P><H2><A name="label59">16.7 Garbage Collection</A></H2><P>An instance of an <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN> </CODE></SPAN><CODE><SPAN class="type">OZ_Extension</SPAN></CODE> class lives on the heap and must be properly copied at each garbage collection. This is realized simply by creating a new instance (automatically allocated on the <EM>to</EM> heap) and initializing it with the appropriate info. In the case of a counter object, we must copy the <CODE>n</CODE> pointer. For this purpose we define a one argument constructor. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">Counter</SPAN>(<SPAN class="type">long</SPAN>*<SPAN class="variablename">p</SPAN>):n(p){}<BR><SPAN class="type">OZ_Extension</SPAN>* <SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">gCollectV</SPAN>() { <SPAN class="keyword">return</SPAN> <SPAN class="keyword">new</SPAN> <SPAN class="type">Counter</SPAN>(n); }</CODE></DD></DL><P> Cloning is a kind of copying used during search rather than garbage collection. Every variable and every data-structure that has <EM>token</EM> equality (rather than structural equality), e. g. <CODE>OZ_Extension</CODE>, is <EM>situated</EM> in a space: its home space, i. e. the computation space in which it was created. When its home space H is cloned, the data-structure D must also be cloned: the clone of D must be situated in the clone of H. In the present case, for simplicity we only intend to support counters at top level; thus, the <CODE>sClone</CODE> method should never be used: </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">OZ_Extension</SPAN>* <SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">sCloneV</SPAN>() { Assert(0); <SPAN class="keyword">return</SPAN> 0; }</CODE></DD></DL><P></P><H2><A name="label60">16.8 Finalization</A></H2><P>When all references to a counter object disappear, we would like the malloced <CODE><SPAN class="type">long</SPAN></CODE> to be freed. We cannot easily register a counter object for finalization from the C++ code (this will have to be delegated to Oz code), but we can provide the implementation of the finalization handler. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="functionname">OZ_BI_define</SPAN>(counter_free,1,0)<BR>{<BR> OZ_declareCounter(0,c);<BR> free(c->n);<BR> <SPAN class="keyword">return</SPAN> PROCEED;<BR>}<BR>OZ_BI_end</CODE></DD></DL><P></P><DIV id="section.counter.object.functor"><H2><A name="section.counter.object.functor">16.9 Native Functor</A></H2><P>We must now package this library as a native functor. This is done by providing the function <CODE>oz_init_module()</CODE> which returns a table of builtins. Here, it must also initialize the static member <CODE><SPAN class="reference">Counter</SPAN>::id</CODE>. </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>,0,1,counter_new},<BR> {<SPAN class="string">"is"</SPAN>,1,1,counter_is},<BR> {<SPAN class="string">"get"</SPAN>,1,1,counter_get},<BR> {<SPAN class="string">"set"</SPAN>,2,0,counter_set},<BR> {<SPAN class="string">"next"</SPAN>,1,1,counter_next},<BR> {<SPAN class="string">"free"</SPAN>,1,0,counter_free},<BR> {0,0,0,0}<BR> };<BR> <SPAN class="reference">Counter</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="counter-obj.cc"><CODE>counter-obj.cc</CODE></A>, we first compile and then create a DLL as follows </P><BLOCKQUOTE class="code"><CODE>oztool c++ -c counter-obj.cc<BR>oztool ld counter-obj.o -o counter-obj.so-`oztool platform`</CODE></BLOCKQUOTE><P></P></DIV><H2><A name="label61">16.10 Oz Wrapper Module</A></H2><P>The counter object native library will now be wrapped in an Oz module that registers every new counter object for finalization. </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">functor</SPAN> <BR><SPAN class="keyword">import</SPAN> <BR> CNT(new:NEW is:Is get:Get set:Set next:Next free:Free)<BR> <SPAN class="keyword">at</SPAN> <SPAN class="string">'counter-obj.so{native}'</SPAN> <BR> Finalize(guardian)<BR><SPAN class="keyword">export</SPAN> <BR> New Is Get Set Next<BR><SPAN class="keyword">define</SPAN> <BR> Register = {Finalize<SPAN class="keyword">.</SPAN>guardian Free}<BR> <SPAN class="keyword">proc</SPAN><SPAN class="variablename"> </SPAN>{<SPAN class="functionname">New</SPAN> C}<BR> {NEW C}<BR> {Register C}<BR> <SPAN class="keyword">end</SPAN> <BR><SPAN class="keyword">end</SPAN></CODE></BLOCKQUOTE><P></P></DIV><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node20.html#chapter.counter.global"><< Prev</A></TD><TD><A href="node19.html">- Up -</A></TD><TD><A href="node22.html#chapter.celloid">Next >></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>
|