#include "tracer.h"

#include <die.h>

#include <pthread.h>

#include <map>

static map< string, int > tracer_map;

static bool tracer_enable_all = 0;

static bool tracer_static_init_flag = 0;

static pthread_mutex_t tracer_mutex; // control access to tracer map
static bool tracer_mutex_flag = 0;

static void tracer_static_init() {

   if( tracer_static_init_flag ) return;

   tracer_static_init_flag = 1;

   pthread_mutex_init( &tracer_mutex, 0 );
   tracer_mutex_flag = 1;
};

void tracer_enable( const string& ClassName ) {

   tracer_static_init();

   TRACE("tracer enable: " << ClassName);

   if( ClassName == "all" ) {

      tracer_enable_all = 1;
      return;
   }

   tracer_map[ ClassName ] = 0;
};

int tracer_count( const string& ClassName ) {

   int Count = 0;

   if( tracer_mutex_flag ) pthread_mutex_lock( &tracer_mutex );
   if( tracer_map.find( ClassName ) == tracer_map.end() ) Count = -1;
   else Count = tracer_map[ ClassName ];
   if( tracer_mutex_flag ) pthread_mutex_unlock( &tracer_mutex );

   return Count;
};

void tracer_dump() {

   TRACE ("tracer dump: types traced: " << tracer_map.size());

   if( tracer_mutex_flag ) pthread_mutex_lock( &tracer_mutex );
   for( map< string, int >::iterator i = tracer_map.begin(); i != tracer_map.end(); ++i ) {

      TRACE ("class: " << i->first << " count: " << i->second);
   }
   if( tracer_mutex_flag ) pthread_mutex_unlock( &tracer_mutex );

   TRACE ("tracer dump: finished");
};

void tracer_ctor( const string& ClassName, int& TracerID ) {

//   assert( tracer_mutex );
   if( tracer_mutex_flag ) pthread_mutex_lock( &tracer_mutex );
   if( tracer_map.find( ClassName ) == tracer_map.end() && !tracer_enable_all ) {
   }
   else {

      int& TracerCount = tracer_map[ ClassName ];
      TracerID = TracerCount++;
   }
   if( tracer_mutex_flag ) pthread_mutex_unlock( &tracer_mutex );
};

void tracer_dtor( const string& ClassName, int& TracerID ) {

   if( tracer_mutex_flag ) pthread_mutex_lock( &tracer_mutex );
   if( tracer_map.find( ClassName ) == tracer_map.end() && !tracer_enable_all ) {
   }
   else {

      int& TracerCount = tracer_map[ ClassName ];
      --TracerCount;
   }
   if( tracer_mutex_flag ) pthread_mutex_unlock( &tracer_mutex );
};

