// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/ObjectDebug.cpp,v 1.15 2005/03/23 18:04:32 kommer Exp $
#if 0
#include <acdk.h>
#include "ObjectDebug.h"
namespace acdk {
namespace lang {
int DebugObjectPool::debugLevel = 8;
DebugObjectPool _debugObjectPool;
void
DebugObjectPool::pushFrame(const char* name)
{
frame = new DebugStackFrame(frame, name);
}
void
DebugObjectPool::popFrame()
{
if (frame) {
DebugStackFrame* tframe = frame->upper;
delete frame;
frame = tframe;
}
}
void
_debugPrint(const char* msg)
{
#ifdef ACDK_DEBUG
sys::coreout << msg << sys::eofl;
#endif //ACDK_DEBUG
}
void
DebugStackFrame::addObject(const acdk::lang::Object* obj, size_t size)
{
#ifdef ACDK_USE_GC
if (obj == 0 /*|| obj->isWeakRef()*/)
return;
++_created;
_BytesAllocated += size;
stack.push_back(obj);
#endif //ACDK_USE_GC
}
bool
DebugStackFrame::hasObject(const acdk::lang::Object* obj, bool recursiv) const
{
std::vector<const acdk::lang::Object*>::const_reverse_iterator it = stack.rbegin();
std::vector<const acdk::lang::Object*>::const_reverse_iterator end = stack.rend();
while (it != end) {
if (*it == obj) {
return true;
}
++it;
}
if (upper != 0 && recursiv == true)
return upper->hasObject(obj);
return false;
}
bool
DebugStackFrame::removeObject(const acdk::lang::Object* obj)
{
#ifdef ACDK_USE_GC
if (obj == 0 /*|| obj->isWeakRef()*/)
return true;
std::vector<const acdk::lang::Object*>::iterator it = stack.begin();
std::vector<const acdk::lang::Object*>::iterator end = stack.end();
while (it != end) {
if (*it == obj) {
stack.erase(it);
++_destroyed;
return true;
}
++it;
}
if (upper)
return upper->removeObject(obj);
_debugObjectPool.print(SBSTR("Try to remove acdk::lang::Object out of: " << name.c_str())->c_str(), 0);
#endif //ACDK_USE_GC
return false;
}
bool
DebugStackFrame::checkRecursivReference(const acdk::lang::Object* robj)
{
if (robj->impl() == 0)
return false;
acdk::lang::Object*obj = robj->impl()/*->getObjectPtr()*/;
if (obj->isMarked()) {
if (DebugObjectPool::debugLevel > 8)
sys::coreout << "Found recursive Reference" << sys::eofl;
return true;
}
ControlPushPopOnStack<ControlObjectSetMarket> _mark(obj);
//dmi::SysFields f = obj->getInternalFields(::acdk::lang::dmi::MiNonStatic);// only collectables
FieldReferences f;
obj->getCollectableFields(f);
FieldReferences::const_iterator it = f.begin();
FieldReferences::const_iterator end = f.end();
for (; it < end; ++it)
{
if (checkRecursivReference(*it) == true)
return true;
}
return false;
}
bool
DebugStackFrame::checkRecursivReferences() const
{
std::vector<const acdk::lang::Object*>::const_reverse_iterator it = stack.rbegin();
std::vector<const acdk::lang::Object*>::const_reverse_iterator end = stack.rend();
for (; it != end; ++it)
{
const acdk::lang::Object* obj = (*it);
if (obj->isMarked() == true) {
if (DebugObjectPool::debugLevel > 8)
sys::coreout << "Found recursive Reference" << sys::eofl;
return true;
}
ControlPushPopOnStack<ControlObjectSetMarket> _mark(obj);
//dmi::SysFields f = const_cast<acdk::lang::Object*>(obj)->getInternalFields();
FieldReferences f;
const_cast<acdk::lang::Object*>(obj)->getCollectableFields(f);
FieldReferences::const_iterator fit = f.begin();
FieldReferences::const_iterator fend = f.end();
for (;fit != fend; ++fit)
{
if (checkRecursivReference(*fit) == true)
return true;
}
}
return false;
}
struct GC_ObjectRelatives
{
bool marked;
std::vector<const acdk::lang::Object*> deps;
};
typedef std::map<const acdk::lang::Object*, GC_ObjectRelatives> GC_ObjectTable;
bool
findNonRecDepends(const acdk::lang::Object* findobject, const acdk::lang::Object* obj, GC_ObjectTable& objectTable)
{
GC_ObjectRelatives& rel = objectTable[obj];
if (rel.marked == true)
return false;
if (rel.deps.size() == 0)
return true;
rel.marked = true;
std::vector<const acdk::lang::Object*>::iterator it = rel.deps.begin();
std::vector<const acdk::lang::Object*>::iterator end = rel.deps.end();
//bool foundrecref = false;
while (it != end) {
if ((*it) != findobject) {
if (objectTable.find(*it) == objectTable.end()) {
rel.marked = false;
return true;
}
if (findNonRecDepends(findobject, *it, objectTable) == true) {
rel.marked = false;
return true;
}
}
++it;
}
rel.marked = false;
return false;
}
bool
DebugStackFrame::_setInFieldToNil(const acdk::lang::Object* obj, bool recursiv)
{
bool foundrefinfield = false;
frombeginning:
ObjectStack::iterator oit = stack.begin();
ObjectStack::iterator oend = stack.end();
for (; oit < oend; ++oit)
{
const acdk::lang::Object* fieldobj = (*oit);
FieldReferences f;
const_cast<acdk::lang::Object*>(fieldobj)->getCollectableFields(f);
FieldReferences::iterator fit = f.begin();
FieldReferences::iterator fend = f.end();
for (; fit != fend; ++fit)
{
const acdk::lang::Object* o = *fit;;
if (o->impl() == obj)
{
*const_cast<acdk::lang::Object*>(o) = Nil;
foundrefinfield = true;
goto frombeginning;
}
}
}
if (recursiv == true && upper != 0)
return upper->_setInFieldToNil(obj, recursiv) || foundrefinfield;
return foundrefinfield;
}
bool
DebugStackFrame::gc(bool recursiv)
{
/** building table, whith key object, and a list of dependensies.
A is hold by B
B is hold by C and A
*/
bool bret = false;
GC_ObjectTable objectTable;
ObjectStack::reverse_iterator oit = stack.rbegin();
ObjectStack::reverse_iterator oend = stack.rend();
for (; oit < oend; ++oit)
{
FieldReferences f;
const_cast<acdk::lang::Object*>(*oit)->getCollectableFields(f);
FieldReferences::const_iterator fit = f.begin();
FieldReferences::const_iterator fend = f.end();
for (; fit < fend; ++fit)
{
acdk::lang::Object* fobj = (*fit)->impl();
objectTable[fobj].deps.push_back(*oit);
}
}
beginsearch:
GC_ObjectTable::iterator tit = objectTable.begin();
GC_ObjectTable::iterator tend = objectTable.end();
for (; tit != tend; ++tit)
{
if ((*tit).first == 0)
continue;
if (findNonRecDepends((*tit).first, (*tit).first, objectTable) == true)
{
objectTable.erase(tit);
goto beginsearch;
}
}
//beginsweap:
tit = objectTable.begin();
tend = objectTable.end();
for (; tit != tend; ++tit)
{
const acdk::lang::Object* optr = (*tit).first;
if (optr == 0)
continue;
if (hasObject(optr, recursiv) == false)
continue;
if (_setInFieldToNil((*tit).first, recursiv) == true)
bret = true;
}
return bret;
/*
restart_gc:
ObjectStack::reverse_iterator it = stack.rbegin();
ObjectStack::reverse_iterator end = stack.rend();
while (it != end) {
if (gc(*it) == true) {
bret = true;
goto restart_gc;
}
++it;
}
return bret;
*/
}
/*
struct GcObject
{
const acdk::lang::Object* obj;
int recRefCount;
GcObject(acdk::lang::Object* o) : obj(o), recRefCount(0) { }
GcObject(const GcObject& other) : obj(other.obj), recRefCount(other.recRefCount) { }
};
*/
//static
bool
DebugStackFrame::gc(const acdk::lang::Object* obj, GcObjectStack& stack)
{
stack[obj] = 0;
ControlPushPopOnStack<ControlObjectSetMarket> _mark(obj);
FieldReferences f;
const_cast<acdk::lang::Object*>(obj)->getCollectableFields(f);
FieldReferences::const_iterator it = f.begin();
FieldReferences::const_iterator end = f.end();
bool retval = false;
for (; it < end; ++it)
{
const acdk::lang::Object* o = *it;
if (o != 0 && o->impl() != 0)
{
if (o->impl()->/*getObjectPtr()->*/isMarked() == true)
{
++stack[o->impl()/*->getObjectPtr()*/];
retval = true;
continue;
}
else
{
retval = gc(o->impl()/*->getObjectPtr()*/, stack) || retval;
}
}
}
return retval;
}
/* not needed
//static
void
DebugStackFrame::setRefRecToNil(const acdk::lang::Object* obj, const acdk::lang::Object* refobj)
{
dmi::SysFields f = obj->getInternalFields();
dmi::SysFields::const_iterator it = f.begin();
dmi::SysFields::const_iterator end = f.end();
bool retval;
while (it != end) {
if ((*it).type == dmi::SysField::FT_Object) {
const acdk::lang::Object* o = (*it).oval;
if (o != 0 && o->getObjectPtr() != 0 && o) {
if (o->getObjectPtr() != refobj)
setRefRecToNil(o->getObjectPtr(), refobj);
if (o->getObjectPtr() == refobj) {
//const_cast<acdk::lang::Object*>(o)->setWeakRef();
//const_cast<acdk::lang::Object*>(o)->releaseRef();
}
}
}
++it;
}
}
*/
void
DebugStackFrame::_setInFieldToNil(const acdk::lang::Object* obj, GcObjectStack& gcstack)
{
GcObjectStack::iterator oit = gcstack.begin();
GcObjectStack::iterator oend = gcstack.end();
for (; oit != oend; ++oit)
{
const acdk::lang::Object* obj = (*oit).first;
FieldReferences f;
const_cast<acdk::lang::Object*>(obj)->getCollectableFields(f);
FieldReferences::iterator fit = f.begin();
FieldReferences::iterator fend = f.end();
for (; fit < fend; ++fit)
{
const acdk::lang::Object* o = *fit;
if (o->impl() == obj)
{
*const_cast<acdk::lang::Object*>(o) = Nil;
return;
}
}
}
}
bool
DebugStackFrame::gc(const acdk::lang::Object* obj)
{
#ifndef ACDK_USE_EXT_REFERER
#ifdef ACDK_USE_GC
if (obj == 0)
return false;
GcObjectStack _gcstack;
if (gc(obj, _gcstack) == false)
return false;
GcObjectStack::iterator it = _gcstack.begin();
GcObjectStack::iterator end = _gcstack.end();
for (; it != end; ++it)
{
if ((*it).first != 0)
{
const acdk::lang::Object* obj = (*it).first;
int rrefc = (*it).second;
int orc = obj->refCount();
if (orc <= rrefc)
{// here only internal recursive reference
if (DebugObjectPool::debugLevel > 8)
sys::coreout << "GC acdk::lang::Object" << sys::eofl;
//_debugObjectPool.removeObject(obj); //delete obj will do that
// avoid, that releaseRef causes delete this;
//_gcstack.erase(it); is not needed, because _gcstack will be destroyed in return
//const_cast<acdk::lang::Object*>(obj)->setWeakRef();
_setInFieldToNil(obj, _gcstack);
//delete obj;
return true;
}
}
}
#endif //ACDK_USE_GC
#endif //ACDK_USE_EXT_REFERER
return false;
}
void
DebugObjectPool::printAllObjects(sys::core_output& os)
{
if (frame == 0)
return;
DebugStackFrame* sictop = frame;
pushFrame("DebugObjectPool::printAllObjects");
try {
DebugStackFrame* cf = sictop;
while (cf != 0) {
cf->printObjects(os);
cf = cf->upper;
}
} catch (...) {
}
popFrame();
}
void
DebugObjectPool::printObjects(sys::core_output& os)
{
if (frame == 0)
return;
DebugStackFrame* sictop = frame;
pushFrame("DebugObjectPool::printObjects");
try {
sictop->printObjects(os);
} catch(...) {
}
popFrame();
}
void
DebugStackFrame::printObjects(sys::core_output& os) const
{
#ifdef ACDK_USE_GC
os << "StackFrame: " << name.c_str() << ". created: " << _created << ", destroyed: " << _destroyed << sys::eofl;
ObjectStack::const_iterator it = stack.begin();
ObjectStack::const_iterator end = stack.end();
os << "Allocated Objects: " << sys::eofl;
const acdk::lang::Object* obj = 0;
int oldDebugLevel = DebugObjectPool::debugLevel;
DebugObjectPool::debugLevel = 8;
for (; it < end; ++it)
{
obj = *it;
//if (obj->isWeakRef() == false)
os << " Object: " << const_cast<acdk::lang::Object*>(obj)->getClass()->getName()->c_str() << "; " << obj->refCount() << " references: " << const_cast<acdk::lang::Object*>(obj)->toString()->c_str() << sys::eofl;
}
os << "End ofAllocated Objects\n" << sys::eofl;
DebugObjectPool::debugLevel = oldDebugLevel;
#endif //ACDK_USE_GC
}
int
DebugObjectPool::objectCount() const
{
if (frame == 0)
return 0;
return frame->objectCount();
}
int
DebugObjectPool::objectAllCount() const
{
const DebugStackFrame* cf = frame;
int erg = 0;
while (cf != 0)
{
erg += cf->objectCount();
cf = cf->upper;
}
return erg;
}
void
DebugObjectPool::addObject(const acdk::lang::Object* obj, size_t size)
{
if (_inDebug == true)
return;
_inDebug = true;
ensureFrame();
if (debugLevel > 8)
sys::coreout << "Add acdk::lang::Object" << sys::eofl; // no more information, because acdk::lang::Object is not initialized here
frame->addObject(obj, size);
_inDebug = false;
}
void
DebugObjectPool::removeObject(const acdk::lang::Object* obj)
{
if (_inDebug == true)
return;
_inDebug = true;
if (obj == 0 || obj->isWeakRef() == true) {
_inDebug = false;
return;
}
ensureFrame();
if (debugLevel > 8)
sys::coreout << "Remove Object:" << const_cast<acdk::lang::Object*>(obj)->getName()->c_str() << sys::eofl;
if (frame->removeObject(obj) == false)
sys::coreout << "Object: " << const_cast<acdk::lang::Object*>(obj)->toString()->c_str() << " not found in DebugObjectPool!" << sys::eofl;
_inDebug = false;
}
bool
DebugObjectPool::hasObject(const acdk::lang::Object* obj) const
{
ensureFrame();
return frame->hasObject(obj);
}
void
DebugObjectPool::print(const char* msg, int level) // = 0
{
if (level <= debugLevel)
sys::coreout << msg << sys::eofl;
}
bool
DebugObjectPool::checkRecursivAllReferences() const
{
const DebugStackFrame* cf = frame;
while (cf != 0) {
if (cf->checkRecursivReferences() == true)
return true;
cf = cf->upper;
}
return false;
}
bool
DebugObjectPool::checkRecursivReferences() const
{
ensureFrame();
return frame->checkRecursivReferences();
}
bool
DebugObjectPool::gc()
{
ensureFrame();
return frame->gc();
}
bool
DebugObjectPool::gcAll()
{
return false;
}
bool
DebugObjectPool::gc(const acdk::lang::Object* obj)
{
ensureFrame();
frame->gc(obj);
return false;
}
} // lang
} // acdk
#endif // 0 |