2005/5/9

     
 

ObjectHeap.h

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/ObjectHeap.h,v 1.19 2005/04/28 15:00:05 kommer Exp $
#ifndef acdk_lang_sys_ObjectHeap_h
#define acdk_lang_sys_ObjectHeap_h

#include "../../Config.h"

#include "SysRefHolder.h"
#include "HeapFrame.h"

template <class T> class RefHolder;
/*
namespace acdk {
namespace lang {

class acdk::lang::Object;
class InterfaceBase;

namespace ref {

class NotifyObjectEventListener;

} //namespace ref 
} //namespace lang 
} // namespace acdk
*/

namespace acdk {
namespace lang {
namespace sys {

using namespace acdk::lang;

ACDK_DECL_SYS_CLASS(HeapFrame);


/** 
  Manages the different Heaps, including Reference Counting, gargabe Collecting etc.
  There is no Instance of this heap.
  
*/

class Allocator;

class ACDK_CORE_PUBLIC ObjectHeap 
{
private:
  /// private constructor. This class is static
  ObjectHeap() { }
public:

/** HeapType declares the Type of heap, with different memory management strategies
  */
enum HeapType 
  {
    /** Objects are reference counted, but no bookkeeping of References will be made. 
        Cyclic references will not be resolved and freed at gc().
        gc() does nothing.      */
    RC_Heap = 0x0001,
    /** Objects are reference counted and collected in the Heap.
        gc() will try to free cyclic references */
    RC_GC_Heap = 0x0002,

    /** Use a seperate PageAllocator with mark/sweep algo */
    PA_Heap = 0x0004,
    
    /** using Boehms Conservative Garbage Collector */
    GC_Heap = 0x0008,

    /** Objects are allocated on the heap, no reference counting, 
        no bookkeeping of references, just allocate and forget.
        garantee of memory leeks.
    */
    Garbage_Heap = 0x0010,
    /*
      Objects are allocated on a seperated heap, 
      on #popFrame() all Objects will be freed. Please take care of
      dangling pointers! 
    */
    Private_Heap = 0x0020,
  };

  /** returns the current allocator */
  static Allocator* allocator();
  

  /** called if RefCount is zero.
    @return true if acdk::lang::Object should be destroyed
  */
  static bool notifyBeforeObjectDestruction(acdk::lang::Object* obj);
  /** will be called after finalize but bufore ~acdk::lang::Object */
  static void notifyWhileObjectDestruction(acdk::lang::Object* obj);
  static void listHeaps(::acdk::lang::ref::NotifyObjectEventListener* listener, bool allthreads);
  /*
    @param flags combination of ListObjectsFlags
  */
  static void listObjects(::acdk::lang::ref::NotifyObjectEventListener* listener, int flags);
  static void listedAllocated(::acdk::lang::ref::NotifyObjectEventListener* listener, int flags, AllocatedType type);
  
  /** 
    returns the count of allocated acdk::lang::Object in current or all Heaps 
    If the current Heap has no tracking, returns 0.
  */
  static int objectCount(bool total = false);
  /** 
  returns the allocated Memory in current or all Heaps.
  If the current Heap has no tracking, returns 0.
  */
  static size_t totalAllocated(bool total = false);
  /** checks if Heap has recursiv References */
  //static bool checkCyclicReferences(bool recursiv = false);
  /** 
    try to free acdk::lang::Object References, which has no external References.
    @return returns true, if an Reference island was found
  */
  static bool gc(bool total = false);
  /** 
    try to free the given acdk::lang::Object, if it has no external References.
    @return returns true, if an Reference island was found
  */
  //static bool gc(const acdk::lang::Object* obj);
  /**
    register this object as new dynamically allocated object 
    */
  static void newHeapObject(acdk::lang::Object* obj);
  /** 
    looks if given acdk::lang::Object is in the current heap
  */
  static bool onHeapAllocated(acdk::lang::Object* obj);
  /** 
    creates a new HeapFrame
    @param heaptype the type of the heap
    RC_Heap
        Objects are reference counted, but no bookkeeping of References will be made. 
        Cyclic references will not be resolved and freed at gc().
        gc() does nothing.      
    
    RC_GC_Heap
        Objects are reference counted and collected in the Heap.
        gc() will try to free cyclic references 
        
    Garbage_Heap
        Objects are allocated on the heap, no reference counting, 
        maybe no bookkeeping of references.
        on #popFrame() all Objects will be freed. Please take care of
        dangling pointers! 
    @param name the name of the heap. Used for debugging purpose or as identifier to delete them.
  
  */
  static void pushFrame(HeapType heaptype = RC_GC_Heap, HeapInfo info = HeapIsThread, const char* name = "");
  /**
    destroys the the top (last pushed) Heap 
  */
  static void popFrame(HeapInfo info = HeapIsThread);
  
  /**
    Make the given HeapFrame as top active HeapFrame
    */
  static void pushFrame(RHeapFrame heap);
  /** 
    destroys the frame, take care, this can have side effects
    @param the name of the heapframe.
    @return true if frame is deleted
  */
  static bool deleteFrame(const char* name);
  /**
    returns the last pushed frame
  */
  static RHeapFrame topHeapFrame();
  /** 
    The which holds globals (not bound to Thread */
  static RHeapFrame globalHeap();
  /** 
    The which hold the statics
    @deprecated
  */
  static RHeapFrame staticHeap();
  /** 
    The which hold the statics
    @deprecated
  */
  static RHeapFrame getStaticFrame() { return staticHeap(); }
  /**
    return the allocator configured to allocate static objects
  */
  Allocator* staticAllocator() { return staticHeap()->allocator(); }
  
  /** used to allocate ThreadLocal */
  static RHeapFrame getThreadLocalHeap();
  /**
    return the allocator specific to this thread
  */
  static Allocator* getThreadLocalAllocator();
  /**
    Registers the object as an static instance. 
    Normally you dont need to call this function by hand, but use 
    registerStaticReference().
    @param object the acdk::lang::Object, which will be stored in a static/global reference
  */
  
  static acdk::lang::Object* newStaticObject(acdk::lang::Object* object);
  /**
    register the an reference to acdk::lang::Object as an static/global reference.
    This reference can be reset clearAllStaticReferences().
    @param reference the Reference to the acdk::lang::Object. 
  */
  static void registerStaticReference(acdk::lang::Object* reference);
  /**
    register the an reference to acdk::lang::Object as an static/global reference.
    Will call releaseRef() at at end of program
  */
  static void registerStaticReference(acdk::lang::Object* reference);
  /**
    clear all via registerStaticReference registered reference (set to Nil).
    Calling this method is maybe dangerous, if other parts of the applications
    rely on these static variables
  */
  static void clearAllStaticReferences();
  /**
    return true if the given object instance is held by a static reference
  */
  static bool isStaticReferenceObject(acdk::lang::Object* obj);

  /** locks the ObjectHeap interface */
  static void lockHeap();
  static void unlockHeap();

  /** removes the heaps connected with the current Thread */
  static void removeThreadHeap();

  /** return the adress of the stack base pointer */
  static unsigned int stackBase();
  static void saveStackBase(unsigned int sp); 

    /**
    return the overal limit of memory usage
  */
  static jlong getMaxMemoryUsage() { return maxMemoryUsage(); }
  /**
    set the overall limit of memory usage
  */
  static void setMaxMemoryUsage(jlong maxmem) { maxMemoryUsage() = maxmem; }
  /**
    return the limit of memory usage inside this thread
  */
  static jlong getThreadMaxMemoryUsage() { return threadMaxMemoryUsage(); }
  static void setThreadMaxMemoryUsage(jlong maxmem) { threadMaxMemoryUsage() = maxmem; }
  static jlong& threadMaxMemoryUsage();
  static jlong& maxMemoryUsage();
  static jlong& curMemUsage();
  static jlong& curThreadMemUsage();
  static jlong getMaxAllocatedMem() { return threadMaxMemoryUsage() < maxMemoryUsage() ? threadMaxMemoryUsage() : maxMemoryUsage(); }

protected:
  /// unsynchronized version
  //static void _addObject(const acdk::lang::Object* obj, size_t size);
  /// unsynchronized version
  static bool _onHeapAllocated(const acdk::lang::Object* obj);
  /// unsynchronized version
  //static bool _removeObject(const acdk::lang::Object* obj);
  /// unsynchronized version
  static acdk::lang::Object* _newStaticObject(acdk::lang::Object* obj);
};

foreign class LockObjectHeap
{
public:
  LockObjectHeap()
  {
    ObjectHeap::lockHeap();
    
  }
  ~LockObjectHeap()
  {
    ObjectHeap::unlockHeap();
  }
};

/**
  different to static_mutex it only locks/unlock if System::isInMain() is true
*/
struct HeapLockMutex
: public static_mutex
{
  void lock();
  void unlock();
};

#ifdef ACDK_MT
  extern HeapLockMutex _heapAccessLock; 
# define HEAPLOCKGUARD() TLockGuard<HeapLockMutex>  lockthis(_heapAccessLock)
# define UNLOCKHEAPGUARD() core_unlock_guard<HeapLockGuard> unlockthis(_heapAccessLock)

#else 

# define HEAPLOCKGUARD() 
# define UNLOCKHEAPGUARD()

#endif //ACDK_MT


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


#endif //acdk_lang_sys_ObjectHeap_h