<!--
  - Authors:
  -   Denys Duchier     <duchier@ps.uni-sb.de>
  -
  - Copyright:
  -   Denys Duchier, 1998
  -
  - Last change:
  -   $Date: 1999/12/16 02:29:13 $ by $Author: duchier $
  -   $Revision: 1.4 $
  -
  - This file is part of Mozart, an implementation
  - of Oz 3
  -    http://www.mozart-oz.org
  -
  - See the file "LICENSE" or
  -    http://www.mozart-oz.org/LICENSE.html
  - for information on usage and redistribution
  - of this file, and for a DISCLAIMER OF ALL
  - WARRANTIES.
  -
  -->
<chapter id=chapter.counter.object>
  <title/Native Counter Objects/
  <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>
  <section proglang=cc>
    <title/Counter Class/
    <p>We derive a new <code/&cc.class;Counter/ class from the base class
<code/&cc.class;OZ_Extension/.
<chunk class=ANONYMOUS><title/counter-obj.cc/
#include "mozart.h"

class Counter : public OZ_Extension {
public:
  long * n;
  Counter();
  Counter(long*);
  static int id;
  virtual int getIdV();
  virtual OZ_Term typeV();
  virtual OZ_Extension* gCollectV(void);
  virtual OZ_Extension* sCloneV(void);
  virtual void gCollectRecurseV(void) {}
  virtual void sCloneRecurseV(void) {}
  virtual OZ_Term printV(int depth = 10);
};
</chunk>
A <code/&cc.class;Counter/ object contains a pointer to a malloced
<code/long/. Why not simply have a member of type <code/long/: 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 <code/&cc.class;Counter/ class provides implementations for a
number of virtual member functions introduced by class
<code/&cc.class;Oz_Extension/. We are now going to explain each of them and
provide the necessary code.</p>
  </section>

  <section>
    <title/Counter Creation/
    <p>For this we need the <code/Counter()/ constructor and the new
builtin <code/counter_new/.  The constructor allocates a new
<code/long/, sets <code/n/ to its address and initializes it
with&nbsp;1.  The builtin creates a new instance of the
<code/&cc.class;Counter/
class, boxes it as an Oz value by invoking <code/OZ_extension/ and
returns the result.
<chunk class=ANONYMOUS><title/counter-obj.cc/
Counter::Counter() { n = new long[1]; n[0]=1; }

OZ_BI_define(counter_new,0,1)
{
  OZ_RETURN(OZ_extension(new Counter));
}
OZ_BI_end
</chunk>
</p>
  </section>

  <section>
    <title/Type Testing/
    <p>Every extension class should be uniquely identified.  This is
the purpose of virtual function <code/getIdV/.  Here we illustrate the
usual way of doing so: the class is equipped with a static <code/id/
member and <code/getIdV()/ returns it.  This static member is
initialized by <code/oz_init_module()/ (see
<ptr to=section.counter.object.functor>).
<chunk class=ANONYMOUS><title/counter-obj.cc/
int Counter::id;
int Counter::getIdV() { return id; }
</chunk>
Your code will also need to test whether some <code/OZ_Term/ is in
fact a boxed <code/&cc.class;Counter/.
<chunk class=ANONYMOUS><title/counter-obj.cc/
inline OZ_Boolean OZ_isCounter(OZ_Term t)
{
  t = OZ_deref(t);
  return OZ_isExtension(t) &&
    OZ_getExtension(t)->getIdV()==Counter::id;
}
</chunk>
Additionally, you should probably provide a builtin to perform this
test in Oz code:
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_BI_define(counter_is,1,1)
{
  OZ_declareDetTerm(0,t);
  OZ_RETURN_BOOL(OZ_isCounter(t));
}
OZ_BI_end
</chunk>
Finally, it would be nice if <code proglang=oz/{Value.type C}/ would
return the atom <code proglang=oz/counter/ when <code proglang=oz/C/
is a counter object.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_Term Counter::typeV() { return OZ_atom("counter"); } 
</chunk>
</p>
  </section>

  <section>
    <title/Expecting Counter Arguments in Builtins/
    <p>Obviously we need a way to unbox counter objects.
<chunk class=ANONYMOUS><title/counter-obj.cc/
inline Counter* OZ_CounterToC(OZ_Term t)
{
  return (Counter*) OZ_getExtension(OZ_deref(t));
}
</chunk>
Now we can define a convenient macro that we can use in the
implementation of a builtin to wait until argument <code/ARG/ is
determined, check that it is a boxed <code/&cc.class;Counter/, and
declare a variable <code/VAR/ to hold a pointer to its unboxed value.
<chunk class=ANONYMOUS><title/counter-obj.cc/
#define OZ_declareCounter(ARG,VAR) \
OZ_declareType(ARG,VAR,Counter*,"counter",OZ_isCounter,OZ_CounterToC)
</chunk>
Next, we illustrate how to use this macro.</p>
  </section>

  <section>
    <title/Operations on Counters/
    <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 (&ie; argument number&nbsp;0) should be a
determined boxed counter and that <code/c/ should be set to point to
its unboxed value.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_BI_define(counter_get,1,1)
{
  OZ_declareCounter(0,c);
  OZ_RETURN_INT(*c->n);
}
OZ_BI_end
</chunk>
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.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_BI_define(counter_set,2,0)
{
  OZ_declareCounter(0,c);
  OZ_declareInt(1,i);
  *c->n=i;
  return PROCEED;
}
OZ_BI_end
</chunk></p>
    <p>Finally, we can define a builtin to obtain the current value
of a counter object and post increment the counter by 1.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_BI_define(counter_next,1,1)
{
  OZ_declareCounter(0,c);
  long i = *c->n;
  *c->n = i+1;
  OZ_RETURN_INT(i);
}
OZ_BI_end
</chunk></p>
  </section>

  <section>
    <title/Printing Support/
    <p>Of course, it would be nice if <code/{Show C}/, when <code/C/
is a counter object, would display <samp/&lt;counter /?{n}<samp/&gt/
where ?{n} is the current value of the counter.  This is easily
achieved by defining virtual function <code/printV/ to return an
appropriate virtual string.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_Term Counter::printV(int depth = 10)
{
  return OZ_mkTupleC("#",3,
		     OZ_atom("&lt;counter "),
		     OZ_int(*n),
		     OZ_atom("&gt;"));
}
</chunk></p>
  </section>

  <section>
    <title/Garbage Collection/
    <p>An instance of an <code/&cc.class;OZ_Extension/ 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/ heap) and initializing it with the
appropriate info.  In the case of a counter object, we must copy the
<code/n/ pointer.  For this purpose we define a one argument
constructor.
<chunk class=ANONYMOUS><title/counter-obj.cc/
Counter::Counter(long*p):n(p){}
OZ_Extension* Counter::gCollectV() { return new Counter(n); }
</chunk>
<!--
THE FOLLOWING IS BULLSHIT IF WE KEEP FINALIZATION SINCE WE DON'T
WANT A CLONE THAT IS NO LONGER REACHABLE TO FREE THE N POINTER

Cloning is a kind of copying used during search rather than garbage
collection.  Every variable and every data-structure that has
<em/token/ equality
(rather than structural equality), &eg; <code/OZ_Extension/, is
<em/situated/ in a space: its home space, &ie; 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, we just need to do the same
thing as the collection method:
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_Extension* Counter::sCloneV() { return gCollectV(); }
</chunk>
This has the effect that clones will share the same <code/n/ pointer:
thus, changing the value of the counter in one space can also be
observed in another.
-->
Cloning is a kind of copying used during search rather than garbage
collection.  Every variable and every data-structure that has
<em/token/ equality
(rather than structural equality), &eg; <code/OZ_Extension/, is
<em/situated/ in a space: its home space, &ie; 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/ method
should never be used:
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_Extension* Counter::sCloneV() { Assert(0); return 0; }
</chunk>
</p>
  </section>

  <section>
    <title/Finalization/
    <p>When all references to a counter object disappear, we would
like the malloced <code/long/ 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.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_BI_define(counter_free,1,0)
{
  OZ_declareCounter(0,c);
  free(c->n);
  return PROCEED;
}
OZ_BI_end
</chunk></p>
  </section>

  <section id=section.counter.object.functor>
    <title/Native Functor/
    <p>We must now package this library as a native functor. This is
done by providing the function <code/oz_init_module()/ which returns a
table of builtins.  Here, it must also initialize the static member
<code/Counter::id/.
<chunk class=ANONYMOUS><title/counter-obj.cc/
OZ_C_proc_interface * oz_init_module(void)
{
  static OZ_C_proc_interface table[] = {
    {"new",0,1,counter_new},
    {"is",1,1,counter_is},
    {"get",1,1,counter_get},
    {"set",2,0,counter_set},
    {"next",1,1,counter_next},
    {"free",1,0,counter_free},
    {0,0,0,0}
  };
  Counter::id = OZ_getUniqueId();
  return table;
}
</chunk>
Assuming the code above is put in file
<ref.extern to="counter-obj.cc"/<file/counter-obj.cc//, we
first compile and then create a DLL as follows
<code display proglang=sh>
oztool c++ -c counter-obj.cc
oztool ld counter-obj.o -o counter-obj.so-`oztool platform`
</code>
</p>
  </section>

  <section>
    <title/Oz Wrapper Module/
    <p>The counter object native library will now be wrapped in an
Oz module that registers every new counter object for finalization.
<code display proglang=oz>
functor
import
   CNT(new:NEW is:Is get:Get set:Set next:Next free:Free)
   at 'counter-obj.so{native}'
   Finalize(guardian)
export
   New Is Get Set Next
define
   Register = {Finalize.guardian Free}
   proc {New C}
      {NEW C}
      {Register C}
   end
end
</code>
</p>
  </section>
</chapter>
<!--
Local Variables:
mode: sgml
mode: auto-fill
sgml-default-dtd-file: "chapter.ced"
sgml-auto-activate-dtd: t
adaptive-fill-mode: nil
End:
-->
