You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
7.9 KiB
203 lines
7.9 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkGarbageCollector.h,v $
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
// .NAME vtkGarbageCollector - Detect and break reference loops
|
|
// .SECTION Description
|
|
// vtkGarbageCollector is used by VTK classes that may be involved in
|
|
// reference counting loops (such as Algorithm <-> Executive). It
|
|
// detects strongly connected components of the reference graph that
|
|
// have been leaked deletes them. The garbage collector uses the
|
|
// ReportReferences method to search the reference graph and construct
|
|
// a net reference count for each connected component. If the net
|
|
// reference count is zero the entire set of objects is deleted.
|
|
// Deleting each component may leak other components, which are then
|
|
// collected recursively.
|
|
//
|
|
// To enable garbage collection for a class, add these members:
|
|
//
|
|
// \code
|
|
//
|
|
// public:
|
|
// virtual void Register(vtkObjectBase* o)
|
|
// {
|
|
// this->RegisterInternal(o, 1);
|
|
// }
|
|
// virtual void UnRegister(vtkObjectBase* o)
|
|
// {
|
|
// this->UnRegisterInternal(o, 1);
|
|
// }
|
|
//
|
|
// protected:
|
|
//
|
|
// virtual void ReportReferences(vtkGarbageCollector* collector)
|
|
// {
|
|
// // Report references held by this object that may be in a loop.
|
|
// this->Superclass::ReportReferences(collector);
|
|
// vtkGarbageCollectorReport(collector, this->OtherObject, "Other Object");
|
|
// }
|
|
// \endcode
|
|
//
|
|
// The implementations should be in the .cxx file in practice.
|
|
// It is important that the reference be reported using the real
|
|
// pointer or smart pointer instance that holds the reference. When
|
|
// collecting the garbage collector will actually set this pointer to
|
|
// NULL. The destructor of the class should be written to deal with
|
|
// this. It is also expected that an invariant is maintained for any
|
|
// reference that is reported. The variable holding the reference
|
|
// must always either be NULL or refer to a fully constructed valid
|
|
// object. Therefore code like "this->Object->UnRegister(this)" must
|
|
// be avoided if "this->Object" is a reported reference because it
|
|
// is possible that the object is deleted before UnRegister returns
|
|
// but then "this->Object" will be left as a dangling pointer. Instead
|
|
// use code like
|
|
//
|
|
// vtkObjectBase* obj = this->Object;
|
|
// this->Object = 0;
|
|
// obj->UnRegister(this);
|
|
//
|
|
// so that the reported reference maintains the invariant.
|
|
//
|
|
// If subclassing from a class that already supports garbage
|
|
// collection, one need only provide the ReportReferences method.
|
|
|
|
#ifndef __vtkGarbageCollector_h
|
|
#define __vtkGarbageCollector_h
|
|
|
|
#include "vtkObject.h"
|
|
#include "vtkGarbageCollectorManager.h" // Needed for singleton initialization.
|
|
|
|
// This function is a friend of the collector so that it can call the
|
|
// internal report method.
|
|
void VTK_COMMON_EXPORT
|
|
vtkGarbageCollectorReportInternal(vtkGarbageCollector*,
|
|
vtkObjectBase*, void*,
|
|
const char*);
|
|
|
|
// This allows vtkObjectBase to get at the methods it needs.
|
|
class vtkObjectBaseToGarbageCollectorFriendship;
|
|
|
|
class VTK_COMMON_EXPORT vtkGarbageCollector : public vtkObject
|
|
{
|
|
public:
|
|
vtkTypeRevisionMacro(vtkGarbageCollector,vtkObject);
|
|
void PrintSelf(ostream& os, vtkIndent indent);
|
|
static vtkGarbageCollector* New();
|
|
|
|
// Description:
|
|
// Collect immediately using any objects whose collection was
|
|
// previously deferred as a root for the reference graph walk.
|
|
// Strongly connected components in the reference graph are
|
|
// identified. Those with a net reference count of zero are
|
|
// deleted. When a component is deleted it may remove references to
|
|
// other components that are not part of the same reference loop but
|
|
// are held by objects in the original component. These removed
|
|
// references are handled as any other and their corresponding
|
|
// checks may be deferred. This method keeps collecting until no
|
|
// deferred collection checks remain.
|
|
static void Collect();
|
|
|
|
// Description:
|
|
// Collect immediately using the given object as the root for a
|
|
// reference graph walk. Strongly connected components in the
|
|
// reference graph are identified. Those with a net reference count
|
|
// of zero are deleted. When a component is deleted it may remove
|
|
// references to other components that are not part of the same
|
|
// reference loop but are held by objects in the original component.
|
|
// These removed references are handled as any other and their
|
|
// corresponding checks may be deferred. This method does continue
|
|
// collecting in this case.
|
|
static void Collect(vtkObjectBase* root);
|
|
|
|
// Description:
|
|
// Push/Pop whether to do deferred collection. Whenever the total
|
|
// number of pushes exceeds the total number of pops collection will
|
|
// be deferred. Code can call the Collect method directly to force
|
|
// collection.
|
|
static void DeferredCollectionPush();
|
|
static void DeferredCollectionPop();
|
|
|
|
// Description:
|
|
// Set/Get global garbage collection debugging flag. When set to 1,
|
|
// all garbage collection checks will produce debugging information.
|
|
static void SetGlobalDebugFlag(int flag);
|
|
static int GetGlobalDebugFlag();
|
|
|
|
protected:
|
|
vtkGarbageCollector();
|
|
~vtkGarbageCollector();
|
|
|
|
private:
|
|
|
|
// Description:
|
|
// Called by UnRegister method of an object that supports garbage
|
|
// collection. The UnRegister may not actually decrement the
|
|
// reference count, but instead hands the reference to the garbage
|
|
// collector. If a reference can be given, this method accepts it
|
|
// from the caller by returning 1. If the reference cannot be
|
|
// accepted then it returns 0. This may be the case when delayed
|
|
// garbage collection is disabled, or when the collector has decided
|
|
// it is time to do a check.
|
|
static int GiveReference(vtkObjectBase* obj);
|
|
|
|
// Description:
|
|
// Called by Register method of an object that supports garbage
|
|
// collection. The Register may not actually increment the
|
|
// reference count if it can take a reference previously handed to
|
|
// the garbage collector. If a reference can be taken, this method
|
|
// hands it back to the caller by returning 1. If no reference is
|
|
// available, returns 0.
|
|
static int TakeReference(vtkObjectBase* obj);
|
|
|
|
// Singleton management functions.
|
|
static void ClassInitialize();
|
|
static void ClassFinalize();
|
|
|
|
//BTX
|
|
friend class vtkGarbageCollectorManager;
|
|
friend class vtkObjectBaseToGarbageCollectorFriendship;
|
|
//ETX
|
|
|
|
// Internal report callback and friend function that calls it.
|
|
virtual void Report(vtkObjectBase* obj, void* ptr, const char* desc);
|
|
friend void VTK_COMMON_EXPORT
|
|
vtkGarbageCollectorReportInternal(vtkGarbageCollector*,
|
|
vtkObjectBase*, void*,
|
|
const char*);
|
|
|
|
private:
|
|
vtkGarbageCollector(const vtkGarbageCollector&); // Not implemented.
|
|
void operator=(const vtkGarbageCollector&); // Not implemented.
|
|
};
|
|
|
|
//BTX
|
|
class vtkSmartPointerBase;
|
|
|
|
// Description:
|
|
// Function to report a reference held by a smart pointer to a collector.
|
|
void VTK_COMMON_EXPORT
|
|
vtkGarbageCollectorReport(vtkGarbageCollector* collector,
|
|
vtkSmartPointerBase& ptr,
|
|
const char* desc);
|
|
|
|
// Description:
|
|
// Function to report a reference held by a raw pointer to a collector.
|
|
template <class T>
|
|
void vtkGarbageCollectorReport(vtkGarbageCollector* collector, T*& ptr,
|
|
const char* desc)
|
|
{
|
|
vtkGarbageCollectorReportInternal(collector, ptr, &ptr, desc);
|
|
}
|
|
//ETX
|
|
|
|
#endif
|
|
|