
- 基于GPT和ZFS的FreeBSD安装 | ...
- 搭建基于VIM的Python IDE | ...
- python的logging库 | ...
- [小工具]生辰八字计算online(Ver.4) | ...
- 带OAuth的twip安装手记 | ...

简单的Delphi对象管理器
原文链接:http://mental.we8log.com/entry/206/my_weblog
分类:Delphi/Object Pascal
TAG:
本文被浏览了349次
原文链接:http://mental.we8log.com/entry/206/my_weblog
分类:Delphi/Object Pascal
TAG:
本文被浏览了349次
《掺和比试》时得到的一个副产品。
原 理很简单,就是创建的对象放到一个池里,暂时不释放,再分配的时候可以重用。对于需要反复大量创建删除同一个类的对象时,或是创建对象成本很高的情况下, 这个东东有一定的作用。另外还弄了一个通用的对象管理,不提供POOL的缓冲,仅提供自动释放,纯粹是为了方便,这个可以不针对特定对象。
使用方法:
uses objmngr;
...
Type
TDummy = Class(....
Constructor Create(...);
Function Init(...) : TDummy;
...
End;
...
Var
DummyPool : TMObjPool;
...
Function TDummy.Init(...) : TDummy;
Begin
...
Result := Self;
End;
...
// Pool
Var
om : IMObjPoolManager;
Begin
om := TMObjPoolManager.Create(DummyPool, 50);
d1 := (om.New As TDummy).Init(...); // Create new dummy object
...
End; // om and all new dummy objects will be released automatically
...
// Nopool
Var
om : IMObjManager;
Begin
om := TMObjManager.Create(50);
d1 := om.New(TDummy.Create(...)) As TDummy;
d2 := om.New(TOther.Create(...)) As TOther;
...
End; // om and all managed objects will be release automatically
...
Initialization
DummyPool := TMObjPool.Create(TDummy, 5000);
...
Finallization
DummyPool.Free;
注意:因为自动创建对象时无法确定构造函数参数,所以只能调用无参数的构造函数,如需初始化对象,则需要再定义一个Init函数供调用。因为Init函数取代了构造函数的功能,所以还需要它返回Self给调用者。
管理单元objmngr.pas源码:
unit objmngr;
{$IFDEF FPC}{$mode objfpc}{$H+}{$ENDIF}
interface
uses
Classes, SysUtils;
Type
TMBucket = Record
Key : TObject;
Value : TObject;
end;
PMBucket = ^TMBucket;
TMHashMap = Class(TObject)
Private
FSize : Integer;
FItems : Array Of TMBucket;
Protected
Function HashFunc(Key : TObject) : Integer;
Function FindKey(Key : TObject) : Integer;
Function FindEmpty(Key : TObject) : Integer;
Function GetItem(Key : TObject) : TObject;
Public
Constructor Create(ASize : Integer);
Destructor Destroy; Override;
Procedure AddItem(Key, Value : TObject);
Procedure DelItem(Key : TObject);
Function PopItem(Key : TObject) : TObject;
Property Items[Key : TObject] : TObject Read GetItem;
End;
TMStack = Class(TObject)
Private
FData : Array Of TObject;
FTop : Integer;
Public
Constructor Create(ASize : Integer);
Destructor Destroy; Override;
Procedure Push(AObj : TObject);
Function Pop : TObject;
Function IsEmpty : Boolean;
End;
TMObjPool = Class(TObject)
Private
FMeta : TClass;
FPool : Array Of TObject;
FIndex : Integer;
FMap : TMHashMap;
FFree : TMStack;
Public
Constructor Create(AMeta : TClass; ASize : Integer);
Destructor Destroy; Override;
Function NewObj : TObject;
Procedure FreeObj(AObj : TObject);
End;
IMObjPoolManager = Interface
Function New : TObject;
End;
TMObjPoolManager = Class(TInterfacedObject, IMObjPoolManager)
Private
FPool : TMObjPool;
FObjs : TMStack;
Public
Function New : TObject; Overload;
Constructor Create(APool : TMObjPool; ASize : Integer = 1000);
Destructor Destroy; Override;
End;
IMObjManager = Interface
Function New(AObj : TObject) : TObject;
End;
TMObjManager = Class(TInterfacedObject, IMObjManager)
Private
FObjs : TMStack;
Public
Function New(AObj : TObject) : TObject; Overload;
Constructor Create(ASize : Integer = 1000);
Destructor Destroy; Override;
End;
implementation
{ TMHashMap }
Constructor TMHashMap.Create(ASize : Integer);
Begin
FSize := ASize;
SetLength(FItems, FSize);
FillChar(FItems[0], FSize * SizeOf(TMBucket), 0);
End;
Destructor TMHashMap.Destroy;
Begin
SetLength(FItems, 0);
Inherited;
End;
Function TMHashMap.HashFunc(Key : TObject) : Integer;
Begin
Result := Integer(Key) Mod FSize;
End;
Function TMHashMap.FindKey(Key : TObject) : Integer;
Var
i, n : Integer;
Begin
n := HashFunc(Key);
Result := -1;
If FItems[n].Key = Key Then
Result := n
Else
Begin
i := n;
Repeat
i := (i + 1) Mod FSize;
If FItems[i].Key = Key Then
Begin
Result := i;
Break;
End;
Until i = n;
End;
End;
Function TMHashMap.FindEmpty(Key : TObject) : Integer;
Var
i, n : Integer;
Begin
n := HashFunc(Key);
If Integer(FItems[n].Key) = 0 Then
Result := n
Else
Begin
i := n;
Repeat
i := (i + 1) Mod FSize;
If Integer(FItems[i].Key) = 0 Then
Begin
Result := i;
Exit;
End;
Until i = n;
Raise Exception.Create('Map is full!');
End;
End;
Function TMHashMap.GetItem(Key : TObject) : TObject;
Var
i : Integer;
Begin
i := FindKey(Key);
If i >= 0 Then
Result := FItems[i].Value
Else
Result := Nil;
End;
Procedure TMHashMap.AddItem(Key, Value : TObject);
Var
i : Integer;
Begin
i := FindEmpty(Key);
FItems[i].Key := Key;
FItems[i].Value := Value;
End;
Procedure TMHashMap.DelItem(Key : TObject);
Var
i : Integer;
Begin
i := FindKey(Key);
If i >= 0 Then
Begin
FItems[i].Key := TObject(0);
FItems[i].Value := Nil;
End;
End;
Function TMHashMap.PopItem(Key : TObject) : TObject;
Var
i : Integer;
Begin
i := FindKey(Key);
If i >= 0 Then
Begin
Result := FItems[i].Value;
FItems[i].Key := TObject(0);
FItems[i].Value := Nil;
End
Else
Result := Nil;
End;
{ TMStack }
Constructor TMStack.Create(ASize : Integer);
Begin
SetLength(FData, ASize);
FTop := 0;
end;
Destructor TMStack.Destroy;
Begin
SetLength(FData, 0);
Inherited;
end;
Procedure TMStack.Push(AObj : TObject);
Begin
FData[FTop] := AObj;
Inc(FTop);
If FTop >= Length(FData) Then
Raise Exception.Create('Queue is full!');
end;
Function TMStack.Pop : TObject;
Begin
If FTop = 0 Then
Raise Exception.Create('Queue is empty!');
Dec(FTop);
Result := FData[FTop];
end;
Function TMStack.IsEmpty : Boolean;
Begin
Result := (FTop = 0);
end;
{ TMObjPool }
Constructor TMObjPool.Create(AMeta : TClass; ASize : Integer);
Begin
FMeta := AMeta;
SetLength(FPool, ASize);
FIndex := 0;
FMap := TMHashMap.Create(ASize * 4);
FFree := TMStack.Create(ASize);
End;
Destructor TMObjPool.Destroy;
Var
i : Integer;
Begin
FFree.Free;
FMap.Free;
For i := 0 To FIndex - 1 Do
FPool[i].Free;
Inherited;
End;
Function TMObjPool.NewObj : TObject;
Var
i : Integer;
Begin
If FFree.IsEmpty Then
Begin
Result := FMeta.Create;
FPool[FIndex] := Result;
i := FIndex;
Inc(FIndex);
End
Else
Begin
i := Integer(FFree.Pop);
Result := FPool[i];
End;
FMap.AddItem(Result, TObject(i));
End;
Procedure TMObjPool.FreeObj(AObj : TObject);
Var
i : Integer;
Begin
i := Integer(FMap.PopItem(AObj));
FFree.Push(TObject(i));
End;
{ TMObjPoolManager }
Constructor TMObjPoolManager.Create(APool : TMObjPool; ASize : Integer);
Begin
FPool := APool;
FObjs := TMStack.Create(ASize);
End;
Destructor TMObjPoolManager.Destroy;
Begin
While Not FObjs.IsEmpty Do
FPool.FreeObj(FObjs.Pop);
FObjs.Free;
Inherited;
end;
Function TMObjPoolManager.New : TObject;
Begin
Result := FPool.NewObj;
FObjs.Push(Result);
end;
{ TMObjManager }
constructor TMObjManager.Create(ASize: Integer);
begin
FObjs := TMStack.Create(ASize);
end;
destructor TMObjManager.Destroy;
begin
While Not FObjs.IsEmpty Do
FObjs.Pop.Free;
FObjs.Free;
Inherited;
end;
function TMObjManager.New(AObj: TObject): TObject;
begin
FObjs.Push(AObj);
Result := AObj;
end;
end.
草草写就,应该还有优化的余地。
推送到[go4pro.org]






评论列表
(单击此处切换显示/隐藏评论)