2005/5/9

     
 

RC_GC_Heap.cpp

artefaktur
// -*- 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/sys/RC_GC_Heap.cpp,v 1.17 2005/03/07 14:02:12 kommer Exp $

#include <acdk.h>
#include "sys.h"
#include "RC_GC_Heap.h"
#include "AllocatorInternals.h"

#include "../ref/NotifyObjectEvent.h"

#  include <typeinfo>

#ifdef _MSC_VER
# pragma warning(disable : 4512)
#endif 

#include <vector>
#include <map>

#include "../Exception.h"

namespace acdk {
namespace lang {
namespace sys {


//using namespace std;
using namespace acdk::lang;
/*
struct GC_ObjectRelatives
{
  bool marked;
  std::vector<const acdk::lang::Object*> deps;
};
typedef std::map<const acdk::lang::Object*, GC_ObjectRelatives> GC_ObjectTable;
*/
/*
//virtual 
void
RC_GC_Heap::add(const acdk::lang::Object* obj, size_t size)
{
  _allocated += size;
  ++_objectCount;
  _stack[obj] = size;
}
*/

//GC_ObjectTable* __currentObjectTable = 0;
/*
//virtual 
bool 
RC_GC_Heap::removeObject(const acdk::lang::Object* obj, bool recursiv)
{
  
  ObjectStack::iterator it = _stack.find(obj);
  bool found = false;
  if (it != _stack.end()) {
    --_objectCount;
    _stack.erase(it);
    found = false;
  }
  if (__currentObjectTable != 0) {
    GC_ObjectTable::iterator fit = __currentObjectTable->find(obj);
    if (fit != __currentObjectTable->end())
      __currentObjectTable->erase(fit);
  }
    
  return found;
}

//virtual 
bool 
RC_GC_Heap::hasObject(const acdk::lang::Object* obj, bool recursiv) const
{
  return _stack.find(obj) != _stack.end();
}

//virtual 
void 
RC_GC_Heap::printObjects(sys::core_output& os, bool recursiv) const
{
  ObjectStack::const_iterator it = _stack.begin();
  ObjectStack::const_iterator end = _stack.end();
  while (it != end) {
    if ((*it).first != 0) {
      const acdk::lang::Object* o = (*it).first;
      os << typeid(*o).name()  << ": " << o->refCount() << sys::eofl; //": " << o->toString()->c_str() << std::end;
    }
    ++it;
  }
  if (recursiv == true && up() != 0)
    up()->printObjects(os, recursiv);
}

//virtual 
int 
RC_GC_Heap::objectCount(bool recursiv) const
{
  return _objectCount;
}

//virtual 
size_t 
RC_GC_Heap::totalAllocated(bool recursiv) const
{
  return _allocated;
}

//virtual 
bool 
RC_GC_Heap::checkCyclicReferences(bool recursiv) const //### not implemented?
{
  return false;
}



*/
/*
void 
RC_GC_Heap::removeAllStaticReferences()
{
  ObjectStack::const_iterator it = _stack.begin();
  ObjectStack::const_iterator end = _stack.end();
  while (it != end) {
    const acdk::lang::Object* obj = (*it).first;
    if (_valid(obj) == true) {
      if ((*it).first != 0 && (*it).first->isStaticRef() == true) {
        if (obj->refCount() == 0)
          sys::coreout << "Refcount acdk::lang::Object " << obj << " is already 0" << sys::eofl;
        const_cast<acdk::lang::Object*>(obj)->finalize();
        obj->releaseRef();
        removeObject((*it).first);
        removeAllStaticReferences();
        return;
      }
    }
    ++it;
  }
}
*/
/*
  dead code
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;
}
*/

/*
dead code

bool
RC_GC_Heap::_setInFieldToNil(const acdk::lang::Object* obj, bool recursiv)
{
  bool foundrefinfield = false;
frombeginning:
  ObjectStack::iterator oit = stack().begin();
  ObjectStack::iterator oend = stack().end();
  
  while (oit != oend) 
  {
    if (!((*oit).second.flags & ObjectMem)) 
    {
      ++oit;
      continue;
    }
    acdk::lang::Object* fieldobj = reinterpret_cast<acdk::lang::Object*>((*oit).first);
    if (_valid(fieldobj) == true) 
    {
      FieldReferences frefs;
      const_cast<acdk::lang::Object*>(fieldobj)->getCollectableFields(frefs);
      FieldReferences::const_iterator fit = frefs.begin();
      FieldReferences::const_iterator fend = frefs.end();
    for (; fit < fend; ++fit)
    {
      const acdk::lang::Object* o = *fit;
      if (o->impl() == obj) 
      {
        bool restart = false;
        if (o->impl() != 0 && o->impl()->refCount() == 1)
          restart = true;
         *const_cast<acdk::lang::Object*>(o) = Nil;//
         foundrefinfield = true;
         if (restart)
          goto frombeginning;
      }
    }
      
    }
    ++oit;
  }
  if (recursiv == true && up() != 0)
    return up()->_setInFieldToNil(obj, recursiv) || foundrefinfield;
  return foundrefinfield;
}

*/


// in pagedheap.cpp
bool doGc(Allocator* allocator, AllocatorObjectsIterator* iterator, bool recursiv);

//virtual 
bool 
RC_GC_Heap::gc(bool recursiv)
{
  TracedRawAllocatorIterator trai(_allocator);
  return doGc(_allocator, &trai, recursiv);
/*
  {
BegincleanUp:
  TracedRawAllocator::ObjectsSet::iterator oit =  _allocator->_heap.begin();
  TracedRawAllocator::ObjectsSet::iterator oend =  _allocator->_heap.end();
  //ObjectStack::iterator oit = _stack.begin();
  //ObjectStack::iterator oend = _stack.end();
    while (oit != oend) 
    {  
      if (!((*oit).second.flags & ObjectMem)) {
       ++oit;
        continue;
      }
      acdk::lang::Object* o = reinterpret_cast<acdk::lang::Object*>((*oit).first);
      if (_valid(o) == false) {
        _allocator->_heap.erase(oit);
        goto BegincleanUp;
      }
      ++oit;
    }
  }
  bool bret = false;
  GC_ObjectTable objectTable;
  __currentObjectTable = &objectTable;
  ObjectStack::reverse_iterator oit = stack().rbegin();
  ObjectStack::reverse_iterator oend = stack().rend();
  while (oit != oend) 
  {
    if (!((*oit).second.flags & ObjectMem)) {
       ++oit;
       continue;
    }
    acdk::lang::Object* o = reinterpret_cast<acdk::lang::Object*>((*oit).first);
    if (_valid(o) == false) {
      //(*oit).first = 0;
      ++oit;
      continue;
    }
    //dmi::SysFields f;
    FieldReferences frefs;
    o->getCollectableFields(frefs);
    FieldReferences::const_iterator fit = frefs.begin();
    FieldReferences::const_iterator fend = frefs.end();
    for (; fit < fend; ++fit)
    {
      acdk::lang::Object* fobj = &(*(*fit));
      if (fobj != 0)
        objectTable[fobj].deps.push_back(o);
    }
   
    ++oit;
  }
beginsearch:
  GC_ObjectTable::iterator tit = objectTable.begin();
  GC_ObjectTable::iterator tend = objectTable.end();
  while (tit != tend) {
    if ((*tit).first == 0) {
      ++tit;
      continue;
    }
    if (findNonRecDepends((*tit).first, (*tit).first, objectTable) == true) {
      objectTable.erase(tit);
      goto beginsearch;
    }
    ++tit;
  }
beginsweap:
  tit = objectTable.begin();
  tend = objectTable.end();
  while (tit != tend) {
    const acdk::lang::Object* optr = (*tit).first;
    if (_valid(optr) == false) {
      ++tit;
      continue;
    }
    
    if (_setInFieldToNil((*tit).first, recursiv) == true) {
      bret = true;
      goto beginsweap;
    }
    ++tit;
  }
  __currentObjectTable = 0;
  return bret;
  */
}


//virtual 
void 
RC_GC_Heap::listObjects(::acdk::lang::ref::NotifyObjectEventListener* listener, int flags)
{
  //don't because race condition: HEAPLOCKGUARD();
  allocator()->listObjects(listener, flags);
}


} // sys
} // lang
} // acdk