吧务
level 14
在某些情况下,需要频繁地创建并销毁一些实例,我们可以把这些实例放在一个缓存队列里面,需要的时候再取出来,省去了创建和销毁的开销。
我给出的代码限定了这些实例是以接口方式实现的,稍做修改就可以适用于所有类型(简单类型、记录类型、类实例、接口都可以的)。请大家斧正。
2014年05月08日 01点05分
1
吧务
level 14
unit BambooGenerics.InterfaceCache;
interface
type
IBambooInterfaceCache<T: IInterface> = interface
function Dequeue: T;
procedure Enqueue(var aIntf: T);
end;
TBambooInterfaceCache<T: IInterface> = class(TInterfacedObject, IBambooInterfaceCache<T>)
public type
TProc_InterfaceCache = reference to procedure(var aIntf: T);
strict private
FLock: TObject;
FCache: array of T;
FCacheSize: Word;
FCount: Integer;
FProcCreateInterface: TProc_InterfaceCache;
FProcBeforeEnqueue: TProc_InterfaceCache;
FThreadSafe: Boolean;
strict private
function Dequeue: T;
procedure Enqueue(var aIntf: T);
public
constructor Create(aProcCreateInterface, aProcBeforeEnqueue: TProc_InterfaceCache; aThreadSafe: Boolean = True; aCacheSize: Word = 1024);
destructor Destroy; override;
end;
implementation
{ TBambooInterfaceCache<T> }
constructor TBambooInterfaceCache<T>.Create(aProcCreateInterface: TProc_InterfaceCache; aProcBeforeEnqueue: TProc_InterfaceCache; aThreadSafe: Boolean; aCacheSize: Word);
begin
Assert(Assigned(aProcCreateInterface));
inherited Create;
FThreadSafe := aThreadSafe;
FProcCreateInterface := aProcCreateInterface;
FProcBeforeEnqueue := aProcBeforeEnqueue;
if FThreadSafe then
FLock := TObject.Create;
FCount := 0;
if aCacheSize = 0 then
FCacheSize := 1
else
FCacheSize := aCacheSize;
SetLength(FCache, FCacheSize);
FCount := 0;
end;
function TBambooInterfaceCache<T>.Dequeue: T;
begin
if FThreadSafe then
TMonitor.Enter(FLock);
if FCount = 0 then
FProcCreateInterface(Result)
else
begin
Dec(FCount);
Result := FCache[FCount];
FCache[FCount] := nil;
end;
if FThreadSafe then
TMonitor.Exit(FLock);
end;
destructor TBambooInterfaceCache<T>.Destroy;
begin
if FThreadSafe then
TMonitor.Enter(FLock);
try
SetLength(FCache, 0);
inherited Destroy;
finally
if FThreadSafe then
begin
TMonitor.Exit(FLock);
FLock.Free;
end;
end;
end;
procedure TBambooInterfaceCache<T>.Enqueue(var aIntf: T);
begin
if not Assigned(aIntf) then
Exit;
if Assigned(FProcBeforeEnqueue) then
begin
FProcBeforeEnqueue(aIntf);
if not Assigned(aIntf) then
Exit;
end;
if FThreadSafe then
TMonitor.Enter(FLock);
if FCount < FCacheSize then
begin
FCache[FCount] := aIntf;
Inc(FCount);
end;
aIntf := nil;
if FThreadSafe then
TMonitor.Exit(FLock);
end;
end.
2014年05月08日 01点05分
2
吧务
level 14
嗯,一发代码前面的空格就被度娘干掉了,大家Ctrl+d一下吧。
2014年05月08日 01点05分
3