///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2006 by Intel Coproration and Carnegie Mellon University    //
// Contacts: casey.j.helfrich @ intel.com                                    //
//           bdr @ cs.cmu.edu                                                //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#ifndef __DEBUGGING_HXX
#define __DEBUGGING_HXX

#include "monitored_value.hxx"
#include "monitored_class.hxx"
#include "signpost.hxx"

// Overall lifecycle
bool dprdebug_open(char*);
bool dprdebug_close();

typedef enum {
  dprdebug_class_type,
  dprdebug_classinfo_type
} dprdebug_memItemType;

// Monitored instance variables
#ifndef DISABLE_DEBUGGING
#define IVAR(type, name)						\
  class dprdebug_ivar_ ## name : public monitored_value<type> {		\
  public:								\
    dprdebug_ivar_ ## name ()            : monitored_value<type>(#type, #name) { } \
    dprdebug_ivar_ ## name (type theVal) : monitored_value<type>(#type, #name, theVal) { } \
  } name;
#else
#define IVAR(type, name) type name;
#endif

// Monitored classes
#ifndef DISABLE_DEBUGGING
#define CLASS(name, parent)						\
  class name : public parent, public monitored_class {			\
    class dprdebug_classinfo_ ## name {					\
    public:								\
      string classname;							\
      dprdebug_classinfo_ ## name () : classname(#name) { dprdebug_insert_memory_item(this,dprdebug_classinfo_type); } \
      ~dprdebug_classinfo_ ## name () { dprdebug_remove_memory_item(this); } \
    } dprdebug_classinfo_instance_ ## name;
#else
#define CLASS(name, parent) class name : public parent {
#endif

#ifndef DISABLE_DEBUGGING
#define CLASSNP(name)							\
  class name : public monitored_class {					\
    class dprdebug_classinfo_ ## name {					\
    public:								\
      string classname;							\
      dprdebug_classinfo_ ## name () : classname(#name) { dprdebug_insert_memory_item(this,dprdebug_classinfo_type); } \
      ~dprdebug_classinfo_ ## name () { dprdebug_remove_memory_item(this); } \
    } dprdebug_classinfo_instance_ ## name;
#else
#define CLASSNP(name) class name {
#endif

// Signposts
void dprdebug_signpost(string name, string file, uint32_t line, string function);
// Events
void dprdebug_event(string name, uint64_t value, uint8_t operation);
// Memory locations
void dprdebug_insert_memory_item(void*,dprdebug_memItemType);
void dprdebug_remove_memory_item(void*);
pair<void*,void*> dprdebug_find_owner_of(void*);

#endif
