2020-10-19 12:12:55 +02:00
|
|
|
// *************************************************************************** }
|
|
|
|
//
|
|
|
|
// Delphi MVC Framework
|
|
|
|
//
|
|
|
|
// Copyright (c) 2010-2020 Daniele Teti and the DMVCFramework Team
|
|
|
|
//
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
//
|
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
unit MVCFramework.LRUCache;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
System.SysUtils, System.Generics.Collections;
|
|
|
|
|
|
|
|
type
|
2020-11-01 18:21:54 +01:00
|
|
|
TMVCLRUCacheAction = reference to function(const Key: string): Boolean;
|
|
|
|
|
2020-10-19 12:12:55 +02:00
|
|
|
TMVCLRUCache<T: class> = class
|
2021-02-12 18:44:43 +01:00
|
|
|
private type
|
2020-10-19 12:12:55 +02:00
|
|
|
TMVCLRUCacheItem = class
|
|
|
|
public
|
|
|
|
Key: string;
|
|
|
|
Value: T;
|
|
|
|
constructor Create(const Key: string; const Item: T);
|
|
|
|
destructor Destroy; override;
|
|
|
|
end;
|
2020-11-01 18:21:54 +01:00
|
|
|
private
|
2020-10-19 12:12:55 +02:00
|
|
|
fCache: TObjectList<TMVCLRUCacheItem>;
|
|
|
|
fCapacity: Integer;
|
|
|
|
public
|
2021-02-12 18:44:43 +01:00
|
|
|
constructor Create(const Capacity: Integer); virtual;
|
|
|
|
destructor Destroy; override;
|
2020-10-19 12:12:55 +02:00
|
|
|
function Contains(const Key: string; out ItemIndex: UInt64): Boolean;
|
|
|
|
procedure Put(const Key: string; const Item: T);
|
|
|
|
function TryGet(const Key: string; out Item: T): Boolean;
|
2020-11-01 18:21:54 +01:00
|
|
|
procedure RemoveIf(const Action: TMVCLRUCacheAction);
|
2020-10-19 12:12:55 +02:00
|
|
|
procedure Clear;
|
2020-11-01 18:21:54 +01:00
|
|
|
function Size: UInt32;
|
|
|
|
procedure Lock;
|
|
|
|
procedure UnLock;
|
2020-10-19 12:12:55 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2020-11-01 18:21:54 +01:00
|
|
|
uses
|
|
|
|
MVCFramework.Logger;
|
|
|
|
|
2020-10-19 12:12:55 +02:00
|
|
|
{ TMVCLRUCache }
|
|
|
|
|
|
|
|
procedure TMVCLRUCache<T>.Clear;
|
|
|
|
begin
|
|
|
|
fCache.Clear;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCLRUCache<T>.Contains(const Key: string; out ItemIndex: UInt64): Boolean;
|
|
|
|
var
|
|
|
|
I: Integer;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
for I := 0 to fCache.Count - 1 do
|
|
|
|
begin
|
|
|
|
if Key = fCache[I].Key then
|
|
|
|
begin
|
|
|
|
ItemIndex := I;
|
|
|
|
Exit(True);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-11-01 18:21:54 +01:00
|
|
|
function TMVCLRUCache<T>.Size: UInt32;
|
|
|
|
begin
|
|
|
|
Result := fCache.Count;
|
|
|
|
end;
|
|
|
|
|
2020-10-19 12:12:55 +02:00
|
|
|
constructor TMVCLRUCache<T>.Create(const Capacity: Integer);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
fCapacity := Capacity;
|
|
|
|
fCache := TObjectList<TMVCLRUCacheItem>.Create(True);
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TMVCLRUCache<T>.Destroy;
|
|
|
|
begin
|
|
|
|
fCache.Free;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2020-11-01 18:21:54 +01:00
|
|
|
procedure TMVCLRUCache<T>.Lock;
|
|
|
|
begin
|
|
|
|
TMonitor.Enter(Self);
|
|
|
|
end;
|
|
|
|
|
2020-10-19 12:12:55 +02:00
|
|
|
procedure TMVCLRUCache<T>.Put(const Key: string; const Item: T);
|
|
|
|
begin
|
2021-02-12 18:44:43 +01:00
|
|
|
Lock;
|
|
|
|
try
|
2021-02-12 18:48:50 +01:00
|
|
|
if fCache.Count = fCapacity then
|
|
|
|
begin
|
2021-02-15 18:17:39 +01:00
|
|
|
fCache.Delete(fCache.Count - 1);
|
2021-02-12 18:44:43 +01:00
|
|
|
end;
|
2021-02-12 18:48:50 +01:00
|
|
|
fCache.Insert(0, TMVCLRUCacheItem.Create(Key, Item));
|
2021-02-12 18:44:43 +01:00
|
|
|
finally
|
|
|
|
UnLock;
|
2020-10-19 12:12:55 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-11-01 18:21:54 +01:00
|
|
|
procedure TMVCLRUCache<T>.RemoveIf(const Action: TMVCLRUCacheAction);
|
|
|
|
var
|
|
|
|
I: Integer;
|
|
|
|
lIndex: Integer;
|
|
|
|
lCacheSize: Integer;
|
|
|
|
begin
|
|
|
|
lIndex := 0;
|
|
|
|
lCacheSize := fCache.Count;
|
|
|
|
while lIndex < lCacheSize do
|
|
|
|
begin
|
|
|
|
if Action(fCache[lIndex].Key) then
|
|
|
|
begin
|
|
|
|
fCache.Delete(lIndex);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Inc(lIndex);
|
|
|
|
end;
|
|
|
|
lCacheSize := fCache.Count;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-19 12:12:55 +02:00
|
|
|
function TMVCLRUCache<T>.TryGet(const Key: string; out Item: T): Boolean;
|
|
|
|
var
|
|
|
|
lItemIndex: UInt64;
|
|
|
|
lCacheItem: TMVCLRUCacheItem;
|
|
|
|
begin
|
2021-02-12 18:44:43 +01:00
|
|
|
Result := Contains(Key, lItemIndex);
|
2020-10-19 12:12:55 +02:00
|
|
|
if Result { and (lItemIndex <> 0) } then
|
|
|
|
begin
|
2021-02-12 18:44:43 +01:00
|
|
|
if lItemIndex > 0 then
|
2020-10-19 12:12:55 +02:00
|
|
|
begin
|
2021-02-12 18:44:43 +01:00
|
|
|
fCache.Exchange(lItemIndex, 0);
|
2020-10-19 12:12:55 +02:00
|
|
|
end;
|
2021-02-12 18:44:43 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// if lItemIndex = 0 then
|
|
|
|
// begin
|
|
|
|
// lCacheItem := fCache[0];
|
|
|
|
// end
|
|
|
|
// else
|
|
|
|
// begin
|
|
|
|
// lCacheItem := fCache.Extract(fCache[lItemIndex]);
|
|
|
|
// fCache.Insert(0, lCacheItem);
|
|
|
|
// end;
|
|
|
|
lCacheItem := fCache[0];
|
2020-10-19 12:12:55 +02:00
|
|
|
Item := lCacheItem.Value;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-11-01 18:21:54 +01:00
|
|
|
procedure TMVCLRUCache<T>.UnLock;
|
|
|
|
begin
|
|
|
|
TMonitor.Exit(Self);
|
|
|
|
end;
|
|
|
|
|
2020-10-19 12:12:55 +02:00
|
|
|
{ TMVCLRUCache<T>.TMVCLRUCacheItem<T> }
|
|
|
|
|
2021-02-12 18:44:43 +01:00
|
|
|
constructor TMVCLRUCache<T>.TMVCLRUCacheItem.Create(const Key: string; const Item: T);
|
2020-10-19 12:12:55 +02:00
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
Self.Key := Key;
|
|
|
|
Self.Value := Item;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TMVCLRUCache<T>.TMVCLRUCacheItem.Destroy;
|
|
|
|
begin
|
|
|
|
Value.Free;
|
|
|
|
Value := nil;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|