unit COMMM;
(*      system
 purpose: Simple COM based memory manager replacement, tested for Delphi 4-7
  author: © 2004, Thaddy de Koning, mailto:thaddy[@]thaddy.com
  status: Use as you like, freeware, but I retain the copyrights.
          No warranties *what*so*ever*. Only Dutch is law applicable.
          (Since it understands the "WhatSoEver" part a little better than most)

 Remarks: Use this if you write COM based applications and/or don't want to
          use ShareMem.pas with BORLNDMM.DLL.
          Also suitable for KOL and KOL dll's.

          *****************************************************************
          This is very simple code, but with far reaching implications.
          *****************************************************************
          Please read these comments carefully before you use this unit and
          make shure you fully understand what it does.
          *****************************************************************
          
Features: + All memory is marshalled through COM.
            This means a.o. that COM provides the reference counting across
            modules, so you don't need the ShareMem unit and don't need to
            distribute BORLNDMM.DLL when using long strings, dynamic arrays
            etc in your dll code.
            COM marshalling simply overrides and ignores Delphi's reference
            counting mechanism.
            During extensive tests I encountered no problems.
          - Because of this it may have an effect on highly specialized code
            that hacks - and I mean hacks - into the Delphi reference count
            mechanism itself, but that is very rare and you will know it when
            you do so. Most programmers need not worry about this.
          + It highly simplifies writing COM based applications since you
            can use Delphi memory access functions without having to worry how
            to allocate the memory. Simply put: getmem and coTaskMemAlloc
            are basically the same and New and (Re)Allocmem provide COM memory
            as well. Even strings and dynamic arrays etc are COM based memory,
            since they rely on these low level routines.
          + This unit guarantees that almost all means of allocating memory with
            Delphi can be used transparantly with COM with the exception of the
            VirtualAlloc - page - related low level WIN32 API.
          + Since it is all COM marshalled memory it is fully shareable
            between COM based applications written in other languages like
            VB or C++ and with some thought even with the scripting host.
          + Your existing code is suddenly COM memory compliant! Just recompile.
          + Your existing dll code maybe managed code (.net) compliant since the
            .NET garbage collection feature seems to rely on COM memory -
            management on the lowest level. Some tests done, but not extensive.
          + It has some basic garbage collection capabilities, even under
            WIN 95/98, since COM releases the orphaned memory if it knows for
            shure that the owning processes are unloaded.
            This does NOT mean your application cannot leak while running!
        -/+ It is a little slower than Delphi's default memorymanager, though,
            but the granularity - 16 bytes - is pretty good.
        -/! Read the warning below! Its use has ambiguities you may overlook.
          
     Use: Simply include it as the *first* unit in the uses clause of your
          project file (.dpr).

 ****************************************************************************
 Warning:
          Do not forget to document that you used it! It is very easy to make
          a mistake later and it will probably break your code if you forget
          about it! Most other memory manager replacements do not have this
          ambiguous disadvantage, so be warned and be very very carefull!
          I highly recommend marking every single unit that may depend on it.
          Trust me, it is very comfortable to use but very easy to forget.
          This may be easily overlooked, even if you use a versioning system.
          *******************************************************************

*)

interface
{.$DEFINE I_HAVE_READ_THE_WARNING}
{$IFNDEF I_HAVE_READ_THE_WARNING}
PLEASE READ THE WARNING!
{$ENDIF}


implementation

uses
  //Both units do not allocate memory, so are safe to use
  Windows,ActiveX;

function ComGetMem(size: Integer): Pointer;
begin
  Result := coTaskMemAlloc(size);
  {$IFOPT D+}
  FillChar(Result^,Size,$CC);
  // = int3, so you get a debug breakpoint if you
  // have troubles
  {$ENDIF}
end;

function ComFreeMem(p: Pointer): Integer;
begin
  coTaskMemFree(P);
  Result:= 0;//!!!Magic!!!  
end;

function ComReallocMem(p: Pointer; size: Integer): Pointer;
begin
  Result:=CoTaskMemRealloc(p,Size);
end;

const
  ComMemoryManager: TMemoryManager = (
  GetMem: ComGetMem;
  FreeMem: ComFreeMem;
  ReallocMem: ComReallocMem);

var
  OldMM: TMemoryManager;

initialization
  GetMemoryManager( OldMM );
  SetMemoryManager( ComMemoryManager );

finalization
  SetMemoryManager( OldMM );

end.
// Was that all? yes it was!

