// @(#)root/base:$Id$
// Author: Matevz Tadel   16/08/2006

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TObjectSpy.h"
#include "TROOT.h"


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TObjectSpy, TObjectRefSpy                                            //
//                                                                      //
// Monitors objects for deletion and reflects the deletion by reverting //
// the internal pointer to zero. When this pointer is zero we know the  //
// object has been deleted. This avoids the unsafe TestBit(kNotDeleted) //
// hack. The spied object must have the kMustCleanup bit set otherwise  //
// you will get an error.                                               //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(TObjectSpy)
ClassImp(TObjectRefSpy)

//______________________________________________________________________________
TObjectSpy::TObjectSpy(TObject *obj, Bool_t fixMustCleanupBit) :
   TObject(), fObj(obj), fResetMustCleanupBit(kFALSE)
{
   // Register the object that must be spied. The object must have the
   // kMustCleanup bit set. If the object has been deleted during a
   // RecusiveRemove() operation, GetObject() will return 0.

   gROOT->GetListOfCleanups()->Add(this);
   if (fObj && !fObj->TestBit(kMustCleanup)) {
      if (fixMustCleanupBit) {
         fResetMustCleanupBit = kTRUE;
         fObj->SetBit(kMustCleanup, kTRUE);
      } else {
         Error("TObjectSpy", "spied object must have the kMustCleanup bit set");
      }
   }
}

//______________________________________________________________________________
TObjectSpy::~TObjectSpy()
{
   // Cleanup.

   if (fObj && fResetMustCleanupBit)
      fObj->SetBit(kMustCleanup, kFALSE);
   gROOT->GetListOfCleanups()->Remove(this);
}

//______________________________________________________________________________
void TObjectSpy::RecursiveRemove(TObject *obj)
{
   // Sets the object pointer to zero if the object is deleted in the
   // RecursiveRemove() operation.

   if (obj == fObj) {
      fObj = 0;
      fResetMustCleanupBit = kFALSE;
   }
}

//______________________________________________________________________________
void TObjectSpy::SetObject(TObject *obj, Bool_t fixMustCleanupBit)
{
   // Set obj as the spy target.

   if (fObj && fResetMustCleanupBit)
      fObj->SetBit(kMustCleanup, kFALSE);
   fResetMustCleanupBit = kFALSE;

   fObj = obj;

   if (fObj && !fObj->TestBit(kMustCleanup)) {
      if (fixMustCleanupBit) {
         fResetMustCleanupBit = kTRUE;
         fObj->SetBit(kMustCleanup, kTRUE);
      } else {
         Error("TObjectSpy", "spied object must have the kMustCleanup bit set");
      }
   }
}


//______________________________________________________________________________
TObjectRefSpy::TObjectRefSpy(TObject *&obj, Bool_t fixMustCleanupBit) :
   fObj(obj), fResetMustCleanupBit(kFALSE)
{
   // Register the object that must be spied. The object must have the
   // kMustCleanup bit set. If the object has been deleted during a
   // RecusiveRemove() operation, GetObject() will return 0.

   gROOT->GetListOfCleanups()->Add(this);
   if (fObj && !fObj->TestBit(kMustCleanup)) {
      if (fixMustCleanupBit) {
         fResetMustCleanupBit = kTRUE;
         fObj->SetBit(kMustCleanup, kTRUE);
      } else {
         Error("TObjectSpy", "spied object must have the kMustCleanup bit set");
      }
   }
}

//______________________________________________________________________________
TObjectRefSpy::~TObjectRefSpy()
{
   // Cleanup.

   if (fObj && fResetMustCleanupBit)
      fObj->SetBit(kMustCleanup, kFALSE);
   gROOT->GetListOfCleanups()->Remove(this);
}

//______________________________________________________________________________
void TObjectRefSpy::RecursiveRemove(TObject *obj)
{
   // Sets the object pointer to zero if the object is deleted in the
   // RecursiveRemove() operation.

   if (obj == fObj) {
      fObj = 0;
      fResetMustCleanupBit = kFALSE;
   }
}
 TObjectSpy.cxx:1
 TObjectSpy.cxx:2
 TObjectSpy.cxx:3
 TObjectSpy.cxx:4
 TObjectSpy.cxx:5
 TObjectSpy.cxx:6
 TObjectSpy.cxx:7
 TObjectSpy.cxx:8
 TObjectSpy.cxx:9
 TObjectSpy.cxx:10
 TObjectSpy.cxx:11
 TObjectSpy.cxx:12
 TObjectSpy.cxx:13
 TObjectSpy.cxx:14
 TObjectSpy.cxx:15
 TObjectSpy.cxx:16
 TObjectSpy.cxx:17
 TObjectSpy.cxx:18
 TObjectSpy.cxx:19
 TObjectSpy.cxx:20
 TObjectSpy.cxx:21
 TObjectSpy.cxx:22
 TObjectSpy.cxx:23
 TObjectSpy.cxx:24
 TObjectSpy.cxx:25
 TObjectSpy.cxx:26
 TObjectSpy.cxx:27
 TObjectSpy.cxx:28
 TObjectSpy.cxx:29
 TObjectSpy.cxx:30
 TObjectSpy.cxx:31
 TObjectSpy.cxx:32
 TObjectSpy.cxx:33
 TObjectSpy.cxx:34
 TObjectSpy.cxx:35
 TObjectSpy.cxx:36
 TObjectSpy.cxx:37
 TObjectSpy.cxx:38
 TObjectSpy.cxx:39
 TObjectSpy.cxx:40
 TObjectSpy.cxx:41
 TObjectSpy.cxx:42
 TObjectSpy.cxx:43
 TObjectSpy.cxx:44
 TObjectSpy.cxx:45
 TObjectSpy.cxx:46
 TObjectSpy.cxx:47
 TObjectSpy.cxx:48
 TObjectSpy.cxx:49
 TObjectSpy.cxx:50
 TObjectSpy.cxx:51
 TObjectSpy.cxx:52
 TObjectSpy.cxx:53
 TObjectSpy.cxx:54
 TObjectSpy.cxx:55
 TObjectSpy.cxx:56
 TObjectSpy.cxx:57
 TObjectSpy.cxx:58
 TObjectSpy.cxx:59
 TObjectSpy.cxx:60
 TObjectSpy.cxx:61
 TObjectSpy.cxx:62
 TObjectSpy.cxx:63
 TObjectSpy.cxx:64
 TObjectSpy.cxx:65
 TObjectSpy.cxx:66
 TObjectSpy.cxx:67
 TObjectSpy.cxx:68
 TObjectSpy.cxx:69
 TObjectSpy.cxx:70
 TObjectSpy.cxx:71
 TObjectSpy.cxx:72
 TObjectSpy.cxx:73
 TObjectSpy.cxx:74
 TObjectSpy.cxx:75
 TObjectSpy.cxx:76
 TObjectSpy.cxx:77
 TObjectSpy.cxx:78
 TObjectSpy.cxx:79
 TObjectSpy.cxx:80
 TObjectSpy.cxx:81
 TObjectSpy.cxx:82
 TObjectSpy.cxx:83
 TObjectSpy.cxx:84
 TObjectSpy.cxx:85
 TObjectSpy.cxx:86
 TObjectSpy.cxx:87
 TObjectSpy.cxx:88
 TObjectSpy.cxx:89
 TObjectSpy.cxx:90
 TObjectSpy.cxx:91
 TObjectSpy.cxx:92
 TObjectSpy.cxx:93
 TObjectSpy.cxx:94
 TObjectSpy.cxx:95
 TObjectSpy.cxx:96
 TObjectSpy.cxx:97
 TObjectSpy.cxx:98
 TObjectSpy.cxx:99
 TObjectSpy.cxx:100
 TObjectSpy.cxx:101
 TObjectSpy.cxx:102
 TObjectSpy.cxx:103
 TObjectSpy.cxx:104
 TObjectSpy.cxx:105
 TObjectSpy.cxx:106
 TObjectSpy.cxx:107
 TObjectSpy.cxx:108
 TObjectSpy.cxx:109
 TObjectSpy.cxx:110
 TObjectSpy.cxx:111
 TObjectSpy.cxx:112
 TObjectSpy.cxx:113
 TObjectSpy.cxx:114
 TObjectSpy.cxx:115
 TObjectSpy.cxx:116
 TObjectSpy.cxx:117
 TObjectSpy.cxx:118
 TObjectSpy.cxx:119
 TObjectSpy.cxx:120
 TObjectSpy.cxx:121
 TObjectSpy.cxx:122
 TObjectSpy.cxx:123
 TObjectSpy.cxx:124
 TObjectSpy.cxx:125
 TObjectSpy.cxx:126
 TObjectSpy.cxx:127
 TObjectSpy.cxx:128
 TObjectSpy.cxx:129
 TObjectSpy.cxx:130
 TObjectSpy.cxx:131
 TObjectSpy.cxx:132
 TObjectSpy.cxx:133