首先,恭祝大家新年快乐,万事如意,事业进步。2014已经过去,QDAC 项目感谢有你的支持和陪伴。2014,感谢有你!
为啥叫SimplePool?因为它太简单了,以至于没有足够的整个代码加上系统自动生成的,也不过100多行,所以直接在下面贴出源码分享给大家:
unit QSimplePool;
interface
uses classes, types, sysutils, syncobjs;
type
TQSimplePool = class;
TQSimplePoolItemNotify = procedure(ASender: TQSimplePool; AData: Pointer)
of object;
TQSimplePoolNewItemEvent = procedure(ASender: TQSimplePool;
var AData: Pointer) of object;
TQSimplePool = class
private
FOnFree: TQSimplePoolItemNotify;
FOnNewItem: TQSimplePoolNewItemEvent;
FOnReset: TQSimplePoolItemNotify;
FBeforePush: TQSimplePoolItemNotify;
FAfterPop: TQSimplePoolItemNotify;
protected
FPool: array of Pointer;
FCount: Integer;
FSize: Integer;
FDataSize: Integer;
FLocker: TCriticalSection;
procedure DoFree(AData: Pointer); // inline;
procedure DoReset(AData: Pointer); // inline;
procedure DoNew(var AData: Pointer); // inline;
public
constructor Create(AMaxSize, ADataSize: Integer); overload;
destructor Destroy; override;
procedure Push(p: Pointer);
function Pop: Pointer;
property Count: Integer read FCount;
property Size: Integer read FSize write FSize;
property OnNewItem: TQSimplePoolNewItemEvent read FOnNewItem
write FOnNewItem;
property OnFree: TQSimplePoolItemNotify read FOnFree write FOnFree;
property OnReset: TQSimplePoolItemNotify read FOnReset write FOnReset;
property BeforePush: TQSimplePoolItemNotify read FBeforePush
write FBeforePush;
property AfterPop: TQSimplePoolItemNotify read FAfterPop write FAfterPop;
end;
implementation
{ TQSimplePool }
constructor TQSimplePool.Create(AMaxSize, ADataSize: Integer);
begin
inherited Create;
FSize := AMaxSize;
FDataSize := ADataSize;
SetLength(FPool, FSize);
FLocker := TCriticalSection.Create;
end;
destructor TQSimplePool.Destroy;
var
I: Integer;
begin
FLocker.Enter;
I := 0;
while I < FCount do
begin
DoFree(FPool[I]);
Inc(I);
end;
FreeAndNil(FLocker);
inherited;
end;
procedure TQSimplePool.DoFree(AData: Pointer);
begin
if Assigned(FOnFree) then
FOnFree(Self, AData)
else
FreeMem(AData);
end;
procedure TQSimplePool.DoNew(var AData: Pointer);
begin
if Assigned(FOnNewItem) then
FOnNewItem(Self, AData)
else
GetMem(AData, FDataSize);
end;
procedure TQSimplePool.DoReset(AData: Pointer);
begin
if Assigned(FOnReset) then
FOnReset(Self, AData)
else
FillChar(AData^, FDataSize, 0);
end;
function TQSimplePool.Pop: Pointer;
begin
Result := nil;
FLocker.Enter;
if FCount > 0 then
begin
Result := FPool[FCount - 1];
Dec(FCount);
end;
FLocker.Leave;
if Result = nil then
DoNew(Result);
if Result <> nil then
begin
DoReset(Result);
if Assigned(FAfterPop) then
FAfterPop(Self,Result);
end;
end;
procedure TQSimplePool.Push(p: Pointer);
var
ADoFree: Boolean;
begin
if Assigned(FBeforePush) then
FBeforePush(Self, p);
FLocker.Enter;
ADoFree := (FCount = FSize);
if not ADoFree then
begin
FPool[FCount] := p;
Inc(FCount);
end;
FLocker.Leave;
if ADoFree then
DoFree(p);
end;
end.如果将它当作一个内存池使用时,可以简单在构造函数中直接传递内存块的大小进去,然后不要设置OnNewItem、OnFree和OnReset事件的响应函数就可以了。如果要做为对象池,则需要至少响应这三个事件,以满足创建对象、释放对象和重置对象时的需要。
一个当做内存池的简单例子:
var APool:TQSimplePool; ... APool := TQSimplePool.Create(1024, SizeOf(TOverlapped)); ... //从池中取出一个元素 var ov:POverlapped; ... ov:=APool.Pop; ... //将元素还回池中 APool.Push(ov);
一个当做对象池的简单例子:
var APool:TQSimplePool; ... APool := TQSimplePool.Create(1024, 0); APool.OnNewItem:=DoNewItem; APool.OnReset:=DoResetItem; APool.OnFree:=DoFreeItem; ... procedure TXXX.DoNewItem(ASender:TQSimplePool;var AData:Pointer); begin AData:=TStringList.Create; end; procedure TXXX.DoResetItem(ASender:TQSimplePool;AData:Pointer) begin TStringList(AData).Clear; end; procedure TXXX.DoFreeItem(ASender:TQSimplePool;AData:Pointer); begin FreeObject(AData); end; ... //从池中取出一个元素 var AList:TStringList; ... AList:=APool.Pop; ... //将元素还回池中 APool.Push(AList);
