How do you design FIFO queue with variable data size?

前端 未结 3 1141
借酒劲吻你
借酒劲吻你 2020-12-18 12:48

I\'m just working on the FIFO queue (the simple one, just what\'s pushed first, pops at first) with the variable data size but I\'m not sure with the way I\'m designing it.

相关标签:
3条回答
  • 2020-12-18 13:02

    I suggest to use the built in TQueue and/or TObjectQueue located in Contnrs.pas. With the lack of Generics one can derive a special TQueue for each datatype used. That would give you type safety inside the rest of your program, while all the casting and pointer related stuff is bundled inside the queue class.

    0 讨论(0)
  • 2020-12-18 13:07

    Why not use:

    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
        Next: PListItem; // pointer to the next data entry, or nil for the last one.
      end;
    

    You would also need a var Root: PListItem = nil; and allocate/deallocate items with New() and Dispose(). You might want to add a var LastItem: PListItem = nil; which contains the last item in your list so you don't have to walk through the whole list every time when you want to add an item.
    While still primitive compared to modern "object-based solutions", a single linked-list is still very efficient for a FIFO solution. Not too elegant but hey, it works well enough. If you want more elegance, build a class around this all!

    0 讨论(0)
  • 2020-12-18 13:17

    I would use memory streams and a TObjectQueue (as Uwe suggested).

    type
      TListQueue = class
      private
        FList: TObjectQueue;
      public
        constructor Create;
        destructor Destroy; override;
        procedure Push(const Value; const Size: Integer);
        procedure Pop(var Value; var Size: Integer);
      end;
    
    implementation
    
    constructor TListQueue.Create;
    begin
      inherited;
      FList := TObjectQueue.Create;
    end;
    
    destructor TListQueue.Destroy;
    begin
      while FList.Count > 0 do
        TMemoryStream(FList.Pop).Free;
      FreeAndNil(FList);
      inherited;
    end;
    
    procedure TListQueue.Push(const Value; const Size: Integer);
    var
      LStream: TMemoryStream;
    begin
      LStream := TMemoryStream.Create;
      LStream.Write(Value, Size);
      FList.Push(LStream);
    end;
    
    procedure TListQueue.Pop(var Value; var Size: Integer);
    var
      LStream: TMemoryStream;
    begin
      if FList.Count > 0 then
      begin
        LStream := TMemoryStream(FList.Pop);
        Size := LStream.Size;
        LStream.Position := 0;
        LStream.Read(Value, Size);
        LStream.Free;
      end;
    end;
    
    0 讨论(0)
提交回复
热议问题