name: MemoryManager
synopsis:

>     g++ [flags ...] file ... -l /isip/tools/lib/$ISIP_BINARY/lib_system.a

>     #include <MemoryManager.h>

>     MemoryManager();
>     void* get();
>     boolean release(voidp ptr);

quick start:

>     // declare MemoryManager object in TRACK mode
>     //
>     MemoryManager mgr_t(sizeof(float), 1024, TRACK);

>     // declare local variable
>     //
>     long size = 100;

>     // allocate a chunk of contiguous memory
>     //
>     float** ptrs_t = (float**)mgr_t.getBlock(size * sizeof(float*));

>     // release that chunk of contiguous memory
>     //
>     mgr_t.releaseBlock(ptrs_t);

description:
The MemoryManager class handles all dynamic memory allocation and deletion. Its primary design speeds up (via block allocation) programs where many objects of the same size are allocated and deleted over time. All objects (scalars and above) override the new and delete methods by means of the MemoryManager, resulting in a significant speedup in dynamic data structures such as graphs and lists.
We support two different modes, TRACK and OPTIMIZE. MemoryManagerTrack is not time efficient and is used when we need to track what happens to memory when it is allocated or released. MemoryManagerOptimize preserves identically-sized blocks of memory. It increases efficiency when we need to allocate a large number of identically-sized blocks. MemoryManagerOptimize and MemoryManagerTrack classes inherit the MemoryManagerBase class, which has virtual functions.
The MemoryMangerBase class defines the interface contract for MemoryManagerOptimize and MemoryManagerTrack. The MemoryManager class has a virtual pointer to either an optimized or tracking MemoryManager. MemoryManagerBase includes virtual functions. Thus, the actual function used is the one defined in the dynamic type of the class reference that invokes it.
dependencies:

- Integral
- SysHeap
- MemoryNode
- MemoryManagerBase
- Error

public constants:

- define the class name:

      static const SysString CLASS_NAME = L"MemoryManager";

- define default arguments to methods:

      static const long ALLOC_SIZE = 32;

      enum MODE {OPTIMIZE = 0, TRACK, DEF_MODE = OPTIMIZE};

- define the default values of the class data:

      static const long DEF_GROW_SIZE = MemoryManagerBase::DEF_GROW_SIZE;

error codes:

- error code indicating MemoryManager class general error:

      static const long ERR = 1200;

- error code indicating attempt to delete non-allocated pointer:

      static const long ERR_NOTFND = 1201;

- error code indicating undeleted memory:

      static const long ERR_NOTEMP = 1202;

protected data:

- define virtual pointer to either an optimized or tracking MemoryManager:

      MemoryManagerBase* virtual_mgr_d;

required public methods:

- static methods:

      static const SysString& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods:

      boolean debug(const unichar* message);

      static boolean setDebug(Integral::DEBUG level_a);

- destructor/constructor(s): the default and copy constructors are private

      ~MemoryManager();

- assign methods:

      these methods are omitted because moving memory between MemoryManager objects is nonsensical

- operator= methods:

      these methods are omitted because moving memory between MemoryManager objects is nonsensical

- i/o methods:

      these methods are omitted because MemoryManager can not write itself to an sof file

- equality methods:

      these methods are omitted because they do not make sense for MemoryManager objects

- memory management methods:

      new and delete are omitted because memory for MemoryManager objects is not managed by the MemoryManager class. clear and cleanUp methods are omitted so the user is not allowed to be careless with memory while expecting cleanUp to mask the effects.

class-specific public methods:

- constructors:

      MemoryManager(long elem_size, long grow_size = DEF_GROW_SIZE);

      MemoryManager(long elem_size, const SysString& name, long grow_size = DEF_GROW_SIZE);

- block-oriented memory allocation and deletion methods:

      void* get();  (TRACK  OPTIMIZE)

      boolean release(void* ptr);  (TRACK  OPTIMIZE)

      void* getBlock(long size);  (TRACK  OPTIMIZE)

      boolean releaseBlock(void* ptr);  (TRACK  OPTIMIZE)

- set methods:

      boolean setGrow(long size);  (TRACK  OPTIMIZE)

      boolean setAllocGrow(long size);  (TRACK  OPTIMIZE)

- wrap the operating system memory methods:

      static boolean reallocateBlock(void*** ptr, long& current_size,long grow_size = DEF_GROW_SIZE);  (TRACK  OPTIMIZE)

      static boolean memset(void* ptr, long val, long size);

      static boolean memcpy(void* dst, const void* src, long size);

      static long memcmp(const void* s1, const void* s2, long size);

- static memory-management methods:

      static void* newStatic(long nbytes);

      static boolean deleteStatic(void* ptr);

      static boolean releaseStatics();

private methods:

- constructor(s): these methods are not required for this class so they are declared private

      MemoryManager();

    MemoryManager(const MemoryManager& arg);

- grow methods:

      boolean grow();(TRACK  OPTIMIZE)

- count node methods:

      boolean countNodes(long& used, long& free) const;(TRACK  OPTIMIZE)

- set mode method:

      boolean setMode(MODE mode, long elem_size, long grow_size);

  examples:
  - This example shows how we allocate and delete memory with MemoryManager:

        // declare MemoryManager object
        //
        MemoryManager mgr_t(sizeof(float), 1024, TRACK);

        // allocate memory
        /
        for (long i = 0; i < 100; i++) {
          ptrs_t[i] = (float*)mgr_t.get();
        }

        // release memory
        //
        for (long i = 0; i < 100; i++) {
          mgr_t.release(ptrs_t[i]);
        }

  - This example shows how we allocate and delete a block of memory with MemoryManager:

        // declare MemoryManager object
        //
        MemoryManager mgr_t(sizeof(float), 1024, TRACK);

        // allocate a chunk of memory
        //
        long size = 1000;
        float** ptrs_t = (float**)mgr_t.getBlock(size * sizeof(float*));

        // release a chunk of memory
        //
        mgr_t.releaseBlock(ptrs_t);

  notes:
  - MemoryManager class inherits the MemoryManagerBase which defines the interface contract for MemoryManagerTrack and MemoryManagerOptimize. The base class has pure virtual functions and the MemoryManager class has a virtual pointer to either an optimized or tracking MemoryManager. The base and derived classes have their own versions of a function, so making the function virtual lets the program automatically decide at run-time which version of the function to use. Pure virtual methods are documented both for MemoryManagerTrack and MemoryManagerOptimize.
  - You must determine at compile-time if you will run an OPTIMIZE or TRACK memory manager. Both managers provide efficient allocation, deletion, and reallocation of fixed size memory chunks through block allocation. The TRACK manager, however, also keeps track of every pointer allocated and deleted and reports discrepencies. OPTIMIZE is the default mode since the TRACK code slows down code considerably.
  - This code also has a hook for Rational Purify and similar memory trackers. Since the block allocation mode reduces the ability of such software to track all allocations and deletions, the code can be compiled with -DPURIFY to disable the special block allocation (in either TRACK or OPTIMIZE).
  - The tracking memory manager has another feature -- each tracking manager registers itself to the system and upon exit each tracking manager is queried to determine if any memory was allocated but not deleted. The manager has to do this before the static managers are deleted so that the output facilities (Console, SysString, etc) are not deleted beforehand.
  - You can always tell which MemoryManager your program was compiled with via the ident command. For example,

          isip111_[1]: ident DoubleLinkedListDiagnose.exe
          DoubleLinkedListDiagnose.exe:
               $MemoryManager: TRACK $

    The string will either be TRACK or OPTIMIZE.