我正在处理FIFO队列(简单的一个,就是先推的内容,首先弹出),但我不确定我的设计方式。我将存储在那里的数据类型将提前知道,让我们说,将是相同的,为这个类的每个示例。我想使用TList,其中记录与以下定义将存储(@大卫-这是D2007的版本,所以我没有可用的Generics.Collections:)
type
PListItem = ^TListItem;
TListItem = record
Size: Integer; // size of the data pointed by the following member
Data: Pointer; // pointer to the target data reserved in memory
end;
使用这样的实现(我在这里假设一切正常,所以没有使用异常处理)
type
TListQueue = class
private
FList: TList;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure Push(const Value; const Size: Integer);
procedure Pop(var Value; var Size: Integer);
end;
constructor TListQueue.Create;
begin
inherited;
FList := TList.Create;
end;
destructor TListQueue.Destroy;
begin
Clear;
FList.Free;
inherited;
end;
procedure TListQueue.Push(const Value; const Size: Integer);
var ListItem: PListItem;
begin
New(ListItem);
ListItem.Size := Size;
ListItem.Data := AllocMem(Size);
Move(Value, ListItem.Data^, Size);
FList.Add(ListItem);
end;
procedure TListQueue.Pop(var Value; var Size: Integer);
var ListItem: PListItem;
begin
if FList.Count > 0 then
begin
ListItem := FList.Items[0];
Size := ListItem^.Size;
Move(ListItem.Data^, Value, ListItem.Size);
FreeMem(ListItem.Data, ListItem.Size);
Dispose(ListItem);
FList.Delete(0);
end;
end;
procedure TListQueue.Clear;
var I: Integer;
ListItem: PListItem;
begin
for I := 0 to FList.Count - 1 do
begin
ListItem := FList.Items[I];
FreeMem(ListItem.Data, ListItem.Size);
Dispose(ListItem);
end;
FList.Clear;
end;
我的问题是:
这是一种有效的方法,如何使FIFO队列(如字符串,流,记录等数据类型)的大小从几个字节到大约1 MB(在流的情况下)?
多谢了
4条答案
按热度按时间px9o7tmv1#
我建议使用Contnrs.pas中内置的TQueue和/或TObjectQueue。由于缺少泛型,可以为所使用的每种数据类型派生一个特殊的TQueue。这将在程序的其余部分中给予类型安全,而所有与类型转换和指针相关的东西都捆绑在队列类中。
wyyhbhjk2#
为什么不用途:
您还需要一个
var Root: PListItem = nil;
,并使用New()和Dispose()分配/取消分配项目。您可能希望添加一个包含列表中最后一个项目的var LastItem: PListItem = nil;
,这样您就不必每次添加项目时都遍历整个列表。虽然与现代的“基于对象的解决方案”相比仍然很原始,但对于FIFO解决方案来说,单个链表仍然非常有效。不太优雅,但嘿,它足够好用了。如果你想要更优雅,围绕这一切构建一个类吧!
ee7vknir3#
我将使用内存流和TObjectQueue(如Uwe所建议的)。
w46czmvw4#
最后,我选择了TStringList来实现这个目标,它看起来工作得很好,但是它不是为多线程设计的。