Pārlūkot izejas kodu

* Fix bug #0036270: optimize TFPSList.AddList and .Assign

git-svn-id: trunk@43473 -
michael 5 gadi atpakaļ
vecāks
revīzija
d21a262a6c
1 mainītis faili ar 54 papildinājumiem un 7 dzēšanām
  1. 54 7
      rtl/objpas/fgl.pp

+ 54 - 7
rtl/objpas/fgl.pp

@@ -41,6 +41,8 @@ type
   TFPSList = class;
   TFPSListCompareFunc = function(Key1, Key2: Pointer): Integer of object;
 
+  { TFPSList }
+
   TFPSList = class(TObject)
   protected
     FList: PByte;
@@ -48,6 +50,7 @@ type
     FCapacity: Integer; { list has room for capacity+1 items, contains room for a temporary item }
     FItemSize: Integer;
     procedure CopyItem(Src, Dest: Pointer); virtual;
+    procedure CopyItems(Src, Dest: Pointer; aCount : Integer); virtual;
     procedure Deref(Item: Pointer); virtual; overload;
     procedure Deref(FromIndex, ToIndex: Integer); overload;
     function Get(Index: Integer): Pointer;
@@ -68,6 +71,7 @@ type
   public
     constructor Create(AItemSize: Integer = sizeof(Pointer));
     destructor Destroy; override;
+    class Function ItemIsManaged : Boolean; virtual;
     function Add(Item: Pointer): Integer;
     procedure Clear;
     procedure Delete(Index: Integer);
@@ -114,6 +118,8 @@ type
     property Current: T read GetCurrent;
   end;
 
+  { TFPGList }
+
   generic TFPGList<T> = class(TFPSList)
   private
     type
@@ -133,6 +139,8 @@ type
     procedure SetLast(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
     function GetFirst: T; {$ifdef FGLINLINE} inline; {$endif}
     procedure SetFirst(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
+  Protected
+    class Function ItemIsManaged : Boolean; override;
   public
     Type
       TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
@@ -460,6 +468,11 @@ begin
   System.Move(Src^, Dest^, FItemSize);
 end;
 
+procedure TFPSList.CopyItems(Src, Dest: Pointer; aCount: Integer);
+begin
+  System.Move(Src^, Dest^, FItemSize*aCount);
+end;
+
 procedure TFPSList.RaiseIndexError(Index : Integer);
 begin
   Error(SListIndexError, Index);
@@ -552,6 +565,11 @@ begin
     Error(SListIndexError, AIndex);
 end;
 
+class function TFPSList.ItemIsManaged: Boolean;
+begin
+  Result:=False;
+end;
+
 
 procedure TFPSList.Clear;
 begin
@@ -838,8 +856,21 @@ var
 begin
   if Obj.ItemSize <> FItemSize then
     Error(SListItemSizeError, 0);
-  for I := 0 to Obj.Count - 1 do
-    Add(Obj[i]);
+  // Do this now.
+  Capacity:=Capacity+Obj.Count;
+  if ItemIsManaged then
+    begin
+    // nothing for it, need to do it manually to give deref a chance.
+    For I:=0 to Obj.Count-1 do
+      Add(Obj[i])
+    end
+  else
+    begin
+    if Obj.Count=0 then
+      exit;
+    CopyItems(Obj.InternalItems[0],InternalItems[FCount],Obj.Count);
+    FCount:=FCount+Obj.Count;
+    end
 end;
 
 procedure TFPSList.Assign(Obj: TFPSList);
@@ -890,7 +921,7 @@ end;
 
 procedure TFPGList.Deref(Item: Pointer);
 begin
-  Finalize(T(Item^));
+ Finalize(T(Item^));
 end;
 
 function TFPGList.Get(Index: Integer): T;
@@ -936,6 +967,11 @@ begin
   inherited SetFirst(@Value);
 end;
 
+class function TFPGList.ItemIsManaged: Boolean;
+begin
+  Result:=IsManagedType(T);
+end;
+
 function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
 begin
   Result := TFPGListEnumeratorSpec.Create(Self);
@@ -976,14 +1012,25 @@ var
   i: Integer;
   
 begin
-  for I := 0 to Source.Count - 1 do
-    Add(Source[i]);
+  if IsManagedType(T) then
+    begin
+    Capacity:=Capacity+Source.Count;
+    for I := 0 to Source.Count - 1 do
+      Add(Source[i]);
+    end
+  else
+    Inherited AddList(TFPSList(source))
 end;
 
 procedure TFPGList.Assign(Source: TFPGList);
 begin
-  Clear;
-  AddList(Source);
+  if IsManagedType(T) then
+    begin
+    Clear;
+    AddList(Source);
+    end
+  else
+    Inherited Assign(TFPSList(source))
 end;
 {$endif VER2_4}