# 16 Native Counter Objects

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.

## 16.1 Counter Class

We derive a new `class` `Counter` class from the base class `class` `OZ_Extension`.

  `#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);
  };`

A `class` `Counter` object contains a pointer to a malloced `long`. Why not simply have a member of type `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.

The `class` `Counter` class provides implementations for a number of virtual member functions introduced by class `class` `Oz_Extension`. We are now going to explain each of them and provide the necessary code.

## 16.2 Counter Creation

For this we need the `Counter()` constructor and the new builtin `counter_new`. The constructor allocates a new `long`, sets `n` to its address and initializes it with 1. The builtin creates a new instance of the `class` `Counter` class, boxes it as an Oz value by invoking `OZ_extension` and returns the result.

  `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`

## 16.3 Type Testing

Every extension class should be uniquely identified. This is the purpose of virtual function `getIdV`. Here we illustrate the usual way of doing so: the class is equipped with a static `id` member and `getIdV()` returns it. This static member is initialized by `oz_init_module()` (see Section 16.9).

  `int Counter::id;
  int Counter::getIdV() { return id; }`

Your code will also need to test whether some `OZ_Term` is in fact a boxed `class` `Counter`.

  `inline OZ_Boolean OZ_isCounter(OZ_Term t)
  {
  t = OZ_deref(t);
  return OZ_isExtension(t) &&
  OZ_getExtension(t)->getIdV()==Counter::id;
  }`

Additionally, you should probably provide a builtin to perform this test in Oz code:

  `OZ_BI_define(counter_is,1,1)
  {
  OZ_declareDetTerm(0,t);
  OZ_RETURN_BOOL(OZ_isCounter(t));
  }
  OZ_BI_end`

Finally, it would be nice if `{Value.type C}` would return the atom `counter` when `C` is a counter object.

  `OZ_Term Counter::typeV() { return OZ_atom("counter"); }`

## 16.4 Expecting Counter Arguments in Builtins

Obviously we need a way to unbox counter objects.

  `inline Counter* OZ_CounterToC(OZ_Term t)
  {
  return (Counter*) OZ_getExtension(OZ_deref(t));
  }`

Now we can define a convenient macro that we can use in the implementation of a builtin to wait until argument `ARG` is determined, check that it is a boxed `class` `Counter`, and declare a variable `VAR` to hold a pointer to its unboxed value.

  `#define OZ_declareCounter(ARG,VAR) \
  OZ_declareType(ARG,VAR,Counter*,"counter",OZ_isCounter,OZ_CounterToC)`

Next, we illustrate how to use this macro.

## 16.5 Operations on Counters

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 `c` should be set to point to its unboxed value.

  `OZ_BI_define(counter_get,1,1)
  {
  OZ_declareCounter(0,c);
  OZ_RETURN_INT(*c->n);
  }
  OZ_BI_end`

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.

We can similarly define a builtin for setting the value of the counter. It takes 2 arguments: a counter object and an integer.

  `OZ_BI_define(counter_set,2,0)
  {
  OZ_declareCounter(0,c);
  OZ_declareInt(1,i);
  *c->n=i;
  return PROCEED;
  }
  OZ_BI_end`

Finally, we can define a builtin to obtain the current value of a counter object and post increment the counter by 1.

  `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`

## 16.6 Printing Support

Of course, it would be nice if `{Show C}`, when `C` is a counter object, would display `<counter` n`>` where n is the current value of the counter. This is easily achieved by defining virtual function `printV` to return an appropriate virtual string.

  `OZ_Term Counter::printV(int depth = 10)
  {
  return OZ_mkTupleC("#",3,
  OZ_atom("<counter "),
  OZ_int(*n),
  OZ_atom(">"));
  }`

## 16.7 Garbage Collection

An instance of an `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 to heap) and initializing it with the appropriate info. In the case of a counter object, we must copy the `n` pointer. For this purpose we define a one argument constructor.

  `Counter::Counter(long*p):n(p){}
  OZ_Extension* Counter::gCollectV() { return new Counter(n); }`

Cloning is a kind of copying used during search rather than garbage collection. Every variable and every data-structure that has token equality (rather than structural equality), e. g. `OZ_Extension`, is situated 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 `sClone` method should never be used:

  `OZ_Extension* Counter::sCloneV() { Assert(0); return 0; }`

## 16.8 Finalization

When all references to a counter object disappear, we would like the malloced `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.

  `OZ_BI_define(counter_free,1,0)
  {
  OZ_declareCounter(0,c);
  free(c->n);
  return PROCEED;
  }
  OZ_BI_end`

## 16.9 Native Functor

We must now package this library as a native functor. This is done by providing the function `oz_init_module()` which returns a table of builtins. Here, it must also initialize the static member `Counter::id`.

  `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;
  }`

Assuming the code above is put in file `counter-obj.cc`, we first compile and then create a DLL as follows

> `oztool c++ -c counter-obj.cc
> oztool ld counter-obj.o -o counter-obj.so-`oztool platform``

## 16.10 Oz Wrapper Module

The counter object native library will now be wrapped in an Oz module that registers every new counter object for finalization.

> `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`