This file is indexed.

/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">&lt;&lt; Prev</A></TD><TD><A href="node19.html">- Up -</A></TD><TD><A href="node22.html#chapter.celloid">Next &gt;&gt;</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>&nbsp;</CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE> class from the base class <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN>&nbsp;</CODE></SPAN><CODE><SPAN class="type">OZ_Extension</SPAN></CODE>. </P><DL class="anonymous"><DD class="code"><CODE>#include&nbsp;<SPAN class="string">&quot;mozart.h&quot;</SPAN>&nbsp;<BR>&nbsp;<BR><SPAN class="keyword">class</SPAN>&nbsp;<SPAN class="type">Counter</SPAN>&nbsp;:&nbsp;<SPAN class="keyword">public</SPAN>&nbsp;<SPAN class="type">OZ_Extension</SPAN>&nbsp;{<BR><SPAN class="keyword">public</SPAN>:<BR>&nbsp;&nbsp;<SPAN class="type">long</SPAN>&nbsp;*&nbsp;<SPAN class="variablename">n</SPAN>;<BR>&nbsp;&nbsp;<SPAN class="functionname">Counter</SPAN>();<BR>&nbsp;&nbsp;<SPAN class="functionname">Counter</SPAN>(<SPAN class="type">long</SPAN>*);<BR>&nbsp;&nbsp;<SPAN class="keyword">static</SPAN>&nbsp;<SPAN class="type">int</SPAN>&nbsp;<SPAN class="variablename">id</SPAN>;<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">int</SPAN>&nbsp;<SPAN class="functionname">getIdV</SPAN>();<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">OZ_Term</SPAN>&nbsp;<SPAN class="functionname">typeV</SPAN>();<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">OZ_Extension</SPAN>*&nbsp;<SPAN class="functionname">gCollectV</SPAN>(<SPAN class="type">void</SPAN>);<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">OZ_Extension</SPAN>*&nbsp;<SPAN class="functionname">sCloneV</SPAN>(<SPAN class="type">void</SPAN>);<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">void</SPAN>&nbsp;<SPAN class="functionname">gCollectRecurseV</SPAN>(<SPAN class="type">void</SPAN>)&nbsp;{}<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">void</SPAN>&nbsp;<SPAN class="functionname">sCloneRecurseV</SPAN>(<SPAN class="type">void</SPAN>)&nbsp;{}<BR>&nbsp;&nbsp;<SPAN class="keyword">virtual</SPAN>&nbsp;<SPAN class="type">OZ_Term</SPAN>&nbsp;<SPAN class="functionname">printV</SPAN>(<SPAN class="type">int</SPAN>&nbsp;<SPAN class="variablename">depth</SPAN>&nbsp;=&nbsp;10);<BR>};</CODE></DD></DL><P> A <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN>&nbsp;</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>&nbsp;</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>&nbsp;</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&nbsp;1. The builtin creates a new instance of the <SPAN class="ignore"><CODE><SPAN class="keyword">class</SPAN>&nbsp;</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>()&nbsp;{&nbsp;n&nbsp;=&nbsp;<SPAN class="keyword">new</SPAN>&nbsp;<SPAN class="type">long</SPAN>[1];&nbsp;n[0]=1;&nbsp;}<BR>&nbsp;<BR><SPAN class="functionname">OZ_BI_define</SPAN>(counter_new,0,1)<BR>{<BR>&nbsp;&nbsp;OZ_RETURN(OZ_extension(<SPAN class="keyword">new</SPAN>&nbsp;<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&nbsp;16.9</A>). </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="type">int</SPAN>&nbsp;<SPAN class="reference">Counter</SPAN>::<SPAN class="variablename">id</SPAN>;<BR><SPAN class="type">int</SPAN>&nbsp;<SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">getIdV</SPAN>()&nbsp;{&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;id;&nbsp;}</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>&nbsp;</CODE></SPAN><CODE><SPAN class="type">Counter</SPAN></CODE>. </P><DL class="anonymous"><DD class="code"><CODE><SPAN class="keyword">inline</SPAN>&nbsp;<SPAN class="type">OZ_Boolean</SPAN>&nbsp;<SPAN class="functionname">OZ_isCounter</SPAN>(<SPAN class="type">OZ_Term</SPAN>&nbsp;<SPAN class="variablename">t</SPAN>)<BR>{<BR>&nbsp;&nbsp;t&nbsp;=&nbsp;OZ_deref(t);<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;OZ_isExtension(t)&nbsp;&amp;&amp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;OZ_getExtension(t)-&gt;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>&nbsp;&nbsp;OZ_declareDetTerm(0,t);<BR>&nbsp;&nbsp;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&nbsp;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>&nbsp;<SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">typeV</SPAN>()&nbsp;{&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;OZ_atom(<SPAN class="string">&quot;counter&quot;</SPAN>);&nbsp;}&nbsp;</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>&nbsp;<SPAN class="type">Counter</SPAN>*&nbsp;<SPAN class="functionname">OZ_CounterToC</SPAN>(<SPAN class="type">OZ_Term</SPAN>&nbsp;<SPAN class="variablename">t</SPAN>)<BR>{<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;(<SPAN class="type">Counter</SPAN>*)&nbsp;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>&nbsp;</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&nbsp;<SPAN class="functionname">OZ_declareCounter</SPAN>(<SPAN class="variablename">ARG</SPAN>,<SPAN class="variablename">VAR</SPAN>)&nbsp;\<BR>OZ_declareType(ARG,VAR,<SPAN class="type">Counter</SPAN>*,<SPAN class="string">&quot;counter&quot;</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.&nbsp;e. argument number&nbsp;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>&nbsp;&nbsp;OZ_declareCounter(0,c);<BR>&nbsp;&nbsp;OZ_RETURN_INT(*c-&gt;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>&nbsp;&nbsp;OZ_declareCounter(0,c);<BR>&nbsp;&nbsp;OZ_declareInt(1,i);<BR>&nbsp;&nbsp;*c-&gt;n=i;<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;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>&nbsp;&nbsp;OZ_declareCounter(0,c);<BR>&nbsp;&nbsp;<SPAN class="type">long</SPAN>&nbsp;<SPAN class="variablename">i</SPAN>&nbsp;=&nbsp;*c-&gt;n;<BR>&nbsp;&nbsp;*c-&gt;n&nbsp;=&nbsp;i+1;<BR>&nbsp;&nbsp;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>&nbsp;<SPAN class="variablename">C</SPAN>}</CODE>, when <CODE>C</CODE> is a counter object, would display <CODE>&lt;counter </CODE><I>n</I><CODE>&gt;</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>&nbsp;<SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">printV</SPAN>(<SPAN class="type">int</SPAN>&nbsp;<SPAN class="variablename">depth</SPAN>&nbsp;=&nbsp;10)<BR>{<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;OZ_mkTupleC(<SPAN class="string">&quot;#&quot;</SPAN>,3,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OZ_atom(<SPAN class="string">&quot;&lt;counter&nbsp;&quot;</SPAN>),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OZ_int(*n),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OZ_atom(<SPAN class="string">&quot;&gt;&quot;</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>&nbsp;</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>*&nbsp;<SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">gCollectV</SPAN>()&nbsp;{&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;<SPAN class="keyword">new</SPAN>&nbsp;<SPAN class="type">Counter</SPAN>(n);&nbsp;}</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.&nbsp;g. <CODE>OZ_Extension</CODE>, is <EM>situated</EM> in a space: its home space, i.&nbsp;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>*&nbsp;<SPAN class="reference">Counter</SPAN>::<SPAN class="functionname">sCloneV</SPAN>()&nbsp;{&nbsp;Assert(0);&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;0;&nbsp;}</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>&nbsp;&nbsp;OZ_declareCounter(0,c);<BR>&nbsp;&nbsp;free(c-&gt;n);<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;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>&nbsp;*&nbsp;<SPAN class="functionname">oz_init_module</SPAN>(<SPAN class="type">void</SPAN>)<BR>{<BR>&nbsp;&nbsp;<SPAN class="keyword">static</SPAN>&nbsp;<SPAN class="type">OZ_C_proc_interface</SPAN>&nbsp;<SPAN class="variablename">table</SPAN>[]&nbsp;=&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;new&quot;</SPAN>,0,1,counter_new},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;is&quot;</SPAN>,1,1,counter_is},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;get&quot;</SPAN>,1,1,counter_get},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;set&quot;</SPAN>,2,0,counter_set},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;next&quot;</SPAN>,1,1,counter_next},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;free&quot;</SPAN>,1,0,counter_free},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{0,0,0,0}<BR>&nbsp;&nbsp;};<BR>&nbsp;&nbsp;<SPAN class="reference">Counter</SPAN>::id&nbsp;=&nbsp;OZ_getUniqueId();<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;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&nbsp;c++&nbsp;-c&nbsp;counter-obj.cc<BR>oztool&nbsp;ld&nbsp;counter-obj.o&nbsp;-o&nbsp;counter-obj.so-`oztool&nbsp;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>&nbsp;<BR><SPAN class="keyword">import</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;CNT(new:NEW&nbsp;is:Is&nbsp;get:Get&nbsp;set:Set&nbsp;next:Next&nbsp;free:Free)<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">at</SPAN>&nbsp;<SPAN class="string">'counter-obj.so{native}'</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;Finalize(guardian)<BR><SPAN class="keyword">export</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;New&nbsp;Is&nbsp;Get&nbsp;Set&nbsp;Next<BR><SPAN class="keyword">define</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;Register&nbsp;=&nbsp;{Finalize<SPAN class="keyword">.</SPAN>guardian&nbsp;Free}<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">proc</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">New</SPAN>&nbsp;C}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{NEW&nbsp;C}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Register&nbsp;C}<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">end</SPAN>&nbsp;<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">&lt;&lt; Prev</A></TD><TD><A href="node19.html">- Up -</A></TD><TD><A href="node22.html#chapter.celloid">Next &gt;&gt;</A></TD></TR></TABLE><HR><ADDRESS><A href="http://www.ps.uni-sb.de/~duchier/">Denys&nbsp;Duchier</A>, <A href="http://www.ps.uni-sb.de/~kornstae/">Leif&nbsp;Kornstaedt</A> and&nbsp;<A href="http://www.ps.uni-sb.de/~schulte/">Christian&nbsp;Schulte</A><BR><SPAN class="version">Version 1.4.0 (20110908185330)</SPAN></ADDRESS></BODY></HTML>