anchor.diff:    strict private
       FStringToId : TDictionary<TStringRec, TStringId>;
       FRefCount : NativeInt;
  -    FIsPersistent : Boolean;
  +    {$ifdef STRINGCACHE_THREADSAFE}
  +      FLock : TCriticalSection;
  +    {$else}
  +      // If threadsafe, always persistent
  +      FIsPersistent : Boolean;
  +    {$endif}
   
       class var FInstance : TStringCache;
       class constructor ClassCreate;
       class destructor ClassDestroy;
  +
  +    procedure Lock; inline;
  +    procedure Unlock; inline;
     private
  -    FIdToString : TList<TStringRec>; // ID is index
  +    FIdToString : TList<TStringRec>;
  +    function GetIsPersistent: Boolean;
  +    procedure SetIsPersistent(const Value: Boolean); // ID is index
     public
       constructor Create;
       destructor Destroy; override;
  
positive.code:     function Add(const Value : string) : TStringId;
      function AddAndGet(const P : PChar; const Length : Integer) : string;
      function Get(const ID : TStringId) : string;
      procedure Clear;
      procedure ByUsage(InOrder : TList<TStringRec>);
  
      procedure IncRef;
      procedure DecRef;
  
      property Persistent : Boolean read FIsPersistent write FIsPersistent;
      class property Instance : TStringCache read FInstance;
    end;
  
  
negative.code: 
  function TStringCache.Get(const ID: TStringId): string;
  begin
    Lock;
    try
      if ID < FIdToString.Count then
        Exit(FIdToString[ID].Value)
      else
        raise Exception.Create(Format('String cache entry with ID %d does not exist', [ID]));
    finally
      Unlock;
    end;
  end;
  
  procedure TStringCache.Clear(const OnDestruction : Boolean);
  var
    I : Integer;
  begin
    // This doesn't need a lock. When threadsafe, never cleared except on destruction
  
    if FRefCount <> 0 then
      raise Exception.Create(Format('Clearing the string cache while objects still rely on it (%d)', [FRefCount]));
  
  