1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    TestGarbageCollector.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkCallbackCommand.h"
17 #include "vtkDebugLeaks.h"
18 #include "vtkGarbageCollector.h"
19 #include "vtkObject.h"
20 #include "vtkSmartPointer.h"
21 
22 // A class that simulates a reference loop and participates in garbage
23 // collection.
24 class vtkTestReferenceLoop: public vtkObject
25 {
26 public:
New()27   static vtkTestReferenceLoop* New() { return new vtkTestReferenceLoop; }
28   vtkTypeMacro(vtkTestReferenceLoop, vtkObject);
29 
Register(vtkObjectBase * o)30   void Register(vtkObjectBase* o) { this->RegisterInternal(o, 1); }
UnRegister(vtkObjectBase * o)31   void UnRegister(vtkObjectBase* o) { this->UnRegisterInternal(o, 1); }
32 
33 protected:
vtkTestReferenceLoop()34   vtkTestReferenceLoop()
35     {
36     this->Other = new vtkTestReferenceLoop(this);
37 #ifdef VTK_DEBUG_LEAKS
38     vtkDebugLeaks::ConstructClass("vtkTestReferenceLoop");
39 #endif
40     }
vtkTestReferenceLoop(vtkTestReferenceLoop * other)41   vtkTestReferenceLoop(vtkTestReferenceLoop* other)
42     {
43     this->Other = other;
44     this->Other->Register(this);
45 #ifdef VTK_DEBUG_LEAKS
46     vtkDebugLeaks::ConstructClass("vtkTestReferenceLoop");
47 #endif
48     }
~vtkTestReferenceLoop()49   ~vtkTestReferenceLoop()
50     {
51     if(this->Other)
52       {
53       this->Other->UnRegister(this);
54       this->Other = 0;
55       }
56     }
57 
ReportReferences(vtkGarbageCollector * collector)58   void ReportReferences(vtkGarbageCollector* collector)
59     {
60     vtkGarbageCollectorReport(collector, this->Other, "Other");
61     }
62 
63   vtkTestReferenceLoop* Other;
64 
65 private:
66   vtkTestReferenceLoop(const vtkTestReferenceLoop&);  // Not implemented.
67   void operator=(const vtkTestReferenceLoop&);  // Not implemented.
68 };
69 
70 // A callback that reports when it is called.
71 static int called = 0;
MyDeleteCallback(vtkObject *,unsigned long,void *,void *)72 static void MyDeleteCallback(vtkObject*, unsigned long, void*, void*)
73 {
74   called = 1;
75 }
76 
77 // Main test function.
TestGarbageCollector(int,char * [])78 int TestGarbageCollector(int,char *[])
79 {
80   // Create a callback that reports when it is called.
81   vtkSmartPointer<vtkCallbackCommand> cc =
82     vtkSmartPointer<vtkCallbackCommand>::New();
83   cc->SetCallback(MyDeleteCallback);
84 
85   // Create an object and delete it immediately.  It should be
86   // immediately collected.
87   vtkTestReferenceLoop* obj = vtkTestReferenceLoop::New();
88   obj->AddObserver(vtkCommand::DeleteEvent, cc);
89   called = 0;
90   obj->Delete();
91   if(!called)
92     {
93     cerr << "Object not immediately collected." << endl;
94     return 1;
95     }
96 
97   // Create an object, enable deferred collection, and delete it.  It
98   // should not be collected yet.
99   obj = vtkTestReferenceLoop::New();
100   obj->AddObserver(vtkCommand::DeleteEvent, cc);
101   vtkGarbageCollector::DeferredCollectionPush();
102   called = 0;
103   obj->Delete();
104   if(called)
105     {
106     cerr << "Object collection not deferred." << endl;
107     return 1;
108     }
109 
110   // Disable deferred collection.  The object should be deleted now.
111   vtkGarbageCollector::DeferredCollectionPop();
112   if(!called)
113     {
114     cerr << "Deferred collection did not collect object." << endl;
115     return 1;
116     }
117 
118   return 0;
119 }
120