#ifndef __Instances_h__
#define __Instances_h__

#include <stdio.h>

aspect InstanceCounting {

  // this pointcut has to be defined by a derived aspect:
  // it defines the classes for which instances should be counted
  pointcut virtual observed() = 0;

  // count constructions and destructions
  advice construction (observed ()) : before () { _created++; }
  advice destruction (observed ())  : after ()  { _destroyed++; }

public:
  // Singleton aspects are allowed to have a default constructor
  InstanceCounting () { set (); }

  // get the numbers
  int created () const { return _created; }
  int destroyed () const { return _destroyed; }

protected:
  // derived aspects are allowed to modify the counters
  void set (int c = 0, int d = 0) { _created = c; _destroyed = d; }
  
private:
  // counters
  int _created;
  int _destroyed;
};

aspect ScopedInstanceCounting : public InstanceCounting {

  // this pointcut has to be defined by a derived aspect:
  // it defines the scope of measurement (a function name)
  pointcut virtual measurement_scope () = 0;

  advice execution (measurement_scope ()) : around () {
    // save the current counters
    int c = created (), d = destroyed ();

    // (re)set the counters to 0
    set ();

    // continue with the intercepted function
    tjp->proceed ();

    // print the statistics
    printf ("Counted instances in execution of \"%s\": "
	    "%d creations, %d destructions\n",
	    tjp->signature (), created (), destroyed ());

    // restore the saved counter values and add what happened here
    set (c + created (), d + destroyed ());
  }
};

#endif // __Instances_h__
