Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Dynamische Arrays "zu Fuß" (https://www.delphipraxis.net/13543-dynamische-arrays-zu-fuss.html)

Luckie 20. Dez 2003 18:51


Dynamische Arrays "zu Fuß"
 
Dynamische Arrays sind ja erst ab D4 und höher bekannt. Aber es gibt ja schon unter D3 Stringliste, was ja im Endeffekt auch nur ein dynmaisches Array of String ist. Da ich damit leibäugle mir D3 Professional ("Delphi for Kids" läßt grüßen) zu kaufen und ich des öfteren doch auf dynamische Arrays angewiesen bin, wollte ich mal fragen, wie man dynamische Arrays zu Fuß, also selber erstellt.

Chewie 20. Dez 2003 19:02

Re: Dynamische Array "zu Fuß"
 
Dynamische Arrays funktionieren ja so, dass bei einem Aufruf von SetLength() soviel Speicher alloziert wird, wie das Array benötigt (also Länge des Array * Elementgröße). Der Zugriff auf ein Speicherelement erfolgt mit der Formel Startadressse + Index * Elementgröße. Bei jedem Aufruf von SetLength wird nun das Array an einen anderen Speicherplatz kopiert und der alte Speicher freigegeben. Pack das ganze in eine schöne Klasse und das sollte es gewesen sein.
OK, du musst für jeden Datentyp eine eigene Implementierung machen, aber das dürfte weitgehend mit C&P zu lösen sein.

So mal ein Beispiel, wie der Umgang mit diesem Objekt wäre. Die Daten selbst wären über einen Pointer abgespeichert, außerdem muss die Anzahl der Einträge gespeichert werden.

Delphi-Quellcode:
//die Klasse heißt TDynArray
myArray := TDynArray.Create(1); //Array mit der Länge erzeugen, im Konstruktor Aufruf von SetLength
myArray[0] := myVar; //myVar an Startposition + 0 schreiben
myArray.SetLength(2); //jetzt werden die ganzen Daten des Array an eine neue Speicherstelle kopiert
myArray.Free;
SetLength würde folgendes tun:
- NeueLänge * Elementgröße Bytes Speicher allozieren
- AlteLänge * Elementgröße Bytes ausgehend von DataPointer in neuen Speicher kopieren
- DataPointer mit alter Länge freigeben
- DataPointer bekommt die Adresse des neuen Speicherbereichs
- Fallunterscheidung: bei Länge 0 kein Kopieren nötig.

Der Zugriff auf ein Element:
- Die Adresse Index * Elementgröße + Datapointer dereferenzieren und in entsprechenden Typ casten

So könnte man das lösen.

Luckie 20. Dez 2003 19:18

Re: Dynamische Array "zu Fuß"
 
Ich habe mal versucht das irgendwie umzusetzten, nach einen Tipp von tommie-lie, der hat sich aber leider unter die Dusche verdrückt.

Bitte nicht lachen, mit Zeigern habe ich es nicht so.
Delphi-Quellcode:
type
  PString = ^String;

var
  StringArray: PString;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  GetMem(StringArray, sizeof(StringArray)+1*sizeof(PString));
  PString(StringArray)^ := Edit1.Text;
end;
Ich bekomme allerdings eine AccessViolation.

Jens Schumann 20. Dez 2003 19:28

Re: Dynamische Arrays "zu Fuß"
 
Hallo Luckie,
möchtest Du wirklich dyn. Array verwenden oder machst Du das nur aus interesse ?
TList liefert eigentlich schon alles was Du brauchst. Wenn Du auf max. Geschwindigkeit
aus bist dann versuche es mit einer verketteten Liste (beispiele finden sich überall).

Ich bin noch nie in eine Situation gekommen die ich nur mit einem dyn. Array lösen konnte.
Deshalb behaupte ich:

!!! Dyn. Array braucht keiner!!!

Ich glaube die dyn. Array's wurden nur für Basic-Programmierer in Delpih aufgenommen.

Hansa 20. Dez 2003 19:37

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von Jens Schumann
Ich bin noch nie in eine Situation gekommen die ich nur mit einem dyn. Array lösen konnte.
Deshalb behaupte ich:

!!! Dyn. Array braucht keiner!!!

Ich glaube die dyn. Array's wurden nur für Basic-Programmierer in Delpih aufgenommen.

Dem ist voll zuzustimmen ! :hello: Ich zumindest verwende ein starres Array, sofern die Anzahl der Elemente vorher klar ist, oder direkt verkettete Listen. Dynamische Arrays hängen irgendwie dazwischen. Aber: ist bspw. ein StringGrid nicht auch ein dyn. Array ?

Luckie 20. Dez 2003 19:40

Re: Dynamische Arrays "zu Fuß"
 
Nun ja, interesse und weil D3 keine dynamischen Arrays kennt.

Mit TList habe ich noch nie gearbeitet. Kennt das D3 denn? Und wie ginge es damit?

Jens Schumann 20. Dez 2003 19:43

Re: Dynamische Arrays "zu Fuß"
 
Hallo Luckie
Zitat:

Zitat von Luckie
Mit TList habe ich noch nie gearbeitet. Kennt das D3 denn?

TList gibt es schon seit D1.

TList ist in der Delphi-Hilfe bestens dokumentiert.

Chewie 20. Dez 2003 19:47

Re: Dynamische Arrays "zu Fuß"
 
Ich würds gar nicht so kompliziert machen und auf einen Typ ausrichte.

Hab hier mal was kleines geschrieben, so wie ichs mir vorstelle:

Delphi-Quellcode:
unit DynArray;

interface
  TDynArray = class
  private
    FDataPointer: Pointer;
    FElementSize: Integer;
    FDataSize: Integer;
    function GetValue(Index: Integer): Integer;
    procedure SetValue(Index: Integer; const Value: Integer);
    procedure CopyData(Destination: Pointer; Size: Integer);
  public
    constructor Create(InitialLength: Integer);
    destructor Destroy; override;
    property Value[Index: Integer]: Integer read GetValue write SetValue;
    procedure SetLength(NewLength: Integer);
  end;

const
  ElementSize = sizeof(Integer);

implementation

{ TDynArray }

procedure TDynArray.CopyData(Destination: Pointer; Size: Integer);
begin
  CopyMemory(Destination, FDataPointer, Size);
end;

constructor TDynArray.Create(InitialLength: Integer);
begin
  FElementSize := ElementSize;
  FDataPointer := nil;
  FDataSize := 0;
  SetLength(InitialLength);
end;

destructor TDynArray.Destroy;
begin
  SetLength(0);
end;

function TDynArray.GetValue(Index: Integer): Integer;
begin
  if Index > Pred(FDataSize) then
    //irgendeine Exception oder sowas auslösen
  Result := Integer(Pointer(Integer(FDataPointer) + Index * FElementSize)^);
end;

procedure TDynArray.SetLength(NewLength: Integer);
var
  NewData: Pointer;
begin
  if NewLength <> 0 then
    FreeMem(FDataPointer, FDataSize * FElementSize);
  GetMem(NewData, NewLength * FElementSize);
  if FDataSize <> 0 then
    CopyData(NewData, FDataSize * FElementSize);
  FreeMem(FDataPointer, FDataSize * FElementSize);
  FDataPointer := NewData;
end;

procedure TDynArray.SetValue(Index: Integer; const Value: Integer);
begin
  if Index > Pred(FDataSize) then
    //irgendeine Exception oder sowas auslösen
  Integer(Pointer(Integer(FDataPointer) + Index * FElementSize)^) := Value;
end;

end.

Luckie 20. Dez 2003 20:04

Re: Dynamische Arrays "zu Fuß"
 
So, nach der Anregung von Herrn Schumann die Lösung mit TList:
Delphi-Quellcode:
type
  StringArray = record
    MyString: String;
  end;
  PStringArray = ^StringArray;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  MyList: Tlist;
  sa: PStringArray;
  Loop: Integer;
begin
  MyList := TList.Create;
  try
    New(sa);
    sa.MyString := 'Egon';
    MyList.Add(sa);
    New(sa);
    sa.MyString := 'Klaus';
    MyList.Add(sa);
    New(sa);
    sa.MyString := 'Michaela';
    MyList.Add(sa);
    for Loop := 0 to myList.Count-1 do
    begin
      sa := MyList.Items[Loop];
      Listbox1.Items.Add(sa.MyString);
    end;
    for Loop := 0 to MyList.Count-1 do
    begin
      sa := MyList.Items[Loop];
      Dispose(sa);
    end;
  finally
    FreeAndNil(MyList);
  end;
end;
Eigentlich auch so in der Hilfe zu finden.

Zu beahcten ist nur, dass man vor dem Hinzufügen, neuen Speicher reserviert (New) für den Record und nach Gebrauch selbigen wieder frei gibt (Dispose). Ist eventuell etwas umständlicher, dafür ist man mit dem Zeiger auf den Record aber felxibeler, man kann mehr Speichern und muss nicht auf mehrdimensionale Arrays zurückgreifen.

Chewie 20. Dez 2003 20:06

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Ist eventuell etwas umständlicher, dafür ist man mit dem Zeiger auf den Record aber felxibeler
Wieso flexibler? Man kann auch ein Array of Pointer oder sogar ein Array of PStringArray nehmen. Dann spart man sich sogar das Typisieren.

Luckie 20. Dez 2003 20:10

Re: Dynamische Arrays "zu Fuß"
 
Flexibeler in dem Sinne, da ich einen Zeiger auf einen Record habe, kann ich so viele Felder wie ich will in dem Record haben. In dem Sinne hätte man ein mehrdimensionales Array.

Chewie 20. Dez 2003 20:15

Re: Dynamische Arrays "zu Fuß"
 
Ja, aber ein Array of Pointer wäre genau so flexibel.
Abgesehen von den Vor- oder Nachteilen, die eine Klassenimplementierung mit sich bringt, natürlich.

Hansa 20. Dez 2003 20:30

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von Chewie
Ja, aber ein Array of Pointer wäre genau so flexibel.

Array of Pointer ? :shock: Was wäre denn das ? Wieder ein Zwischending zwichen Array und Listen/Bäumen. Mit dem Unterschied, daß die Elemente nicht unbedingt gleich sein müssen. Mir dem new und dispose wird lediglich Speicherplatz reserviert/freigegeben, aber dynamisch. Was zu Listen/Bäumen da noch fehlt, ist lediglich noch die Verkettung.

Chewie 20. Dez 2003 20:39

Re: Dynamische Arrays "zu Fuß"
 
Ein Array ist eine Liste, allerdings eine sequenzielle. Ob der Datentyp Pointer, Integer oder Mohnbrötchen ist, spielt überhaupt keine Rolle. Ein Array mit Datentyp Pointer hat auch nicht mehr (oder weniger) zu tun mit einer verketteten Liste. Dort kannst du ja als Datentyp bei dem Wert Pointer angeben.

Luckie 20. Dez 2003 21:14

Re: Dynamische Arrays "zu Fuß"
 
Verdammt. TList ist in Classes drin. Das kann ich ja nun gar nicht brauchen, wen ich ohne VCL programmiere, das sind gleich wieder 130 KB mehr. :evil:

nailor 20. Dez 2003 21:58

Re: Dynamische Arrays "zu Fuß"
 
Aber falls du die D3Prof-Version hättest, könntest du den TList Code rauskopieren, und kämst auf unter 130 KB...

Luckie 20. Dez 2003 22:02

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von Nailor
Aber falls du die D3Prof-Version hättest, könntest du den TList Code rauskopieren, und kämst auf unter 130 KB...

:zwinker: Was meinst du, was ich gerade gemacht habe mit einer "geliehenen" D5 Enterprise, die ich nicht benutze. Copyright vonBorland noch drüber gesetzt und es sollte OK sein. Musste allerdings selbst noch etwasHand anlegen, damit es ohne SysUtils läuft.

choose 20. Dez 2003 22:18

Re: Dynamische Arrays "zu Fuß"
 
Hallo Luckie,

der Nachteil bei Lösungen, die generisch mit Pointern arbeiten (zB TList) liegt in der fehlenden Fähigkeit, mit Typen zu arbeiten. Der Nachteil von Verketteten Listen liegt in dem relativ hohen Aufwand der Verwaltung.

Die Folgende Lösung habe ich zu DOS-Zeiten häufig verwendet:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
type
  TMyType = Integer;
  TMyArray = array[0..MaxInt div SizeOf(TMyType)-1] of TMyType;
  PMyArray = ^TMyArray;
var
  myArray : PMyArray;
  mySize : Integer;
begin
  mySize:= 137*42;
  GetMem(myArray, SizeOf(TMyType)*mySize);
  try
    myArray^[0]:= 1;
    myArray^[1]:= 2;
    myArray^[2]:= myArray^[0]+myArray^[1];
  finally
    FreeMem(myArray);
  end;
end;
der Nachteil ist, dass Du das Ausmaß des Arrays nicht unmittelbar über Low und High ermitteln kannst (es muss zusätzlich, zB in einem Record, die Größe festgehalten werden) und die Indexberechnung bei höherdimensionalen Arrays nur dann funktioniert, wenn die "inneren" Dimensionen fest sind.
Darüber hinaus musst Du (wie bei den anderen Lösungen) die Speicherverwaltung selbst implementieren musst (um Gegensatz zu dynamischen Arrays, bei denen eine transparente Referenzzählung vom Compiler übernommen wird). Da Du ohnehin D6 besitzt, würde ich Dir empfehlen, weiterhin dynamische Arrays zu verwenden. Falls Du mit Klassen arbeitest, könntest Du eine Lösung, die typensicher ist, mit dem Bei Google sucheniterator pattern und dem Bei Google suchenvisitor pattern erreichen.

Luckie 20. Dez 2003 22:37

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von choose
Da Du ohnehin D6 besitzt, würde ich Dir empfehlen, weiterhin dynamische Arrays zu verwenden.

Ja, klar, aber da ich in Erwägung ziehe Programme zu verkaufen und ich dazu eine Professional brauche, wäre das günstigste mir "Delphi for Kids" zu zu legen, wo D3 Prof drin ist und das ganze für 25 Euro. :zwinker: Bisher habe ich noch nichts spezielles aus D6 gebraucht, außer den Dynamischen Arrays. Aber dafür habe ich mir ja jetzt einen Ersatz geschaffen.

w3seek 20. Dez 2003 23:26

Re: Dynamische Arrays "zu Fuß"
 
Hier eine aehnliche Implementierung von TList (allerdings als verkettete liste) von einem sehr alten projekt von mir:

Delphi-Quellcode:
type
{ ****************************************************************************
  * TList                                                                   *
  **************************************************************************** }
  PListItem = ^TListItem;
  TListItem = record
    Data: Pointer;
    Prev: PListItem;
    Next: PListItem;
  end;

  TList = class
  private
    FStart: PListItem;
    FEnd: PListItem;
    FCount: Integer;
    FCurrent: PListItem;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Clear;
    procedure Add(Data: Pointer);
    function Count: Integer;
    function GetItem(Index: Integer): Pointer;
    procedure SetItem(Index: Integer; Data: Pointer);
    function Remove(Data: Pointer): Boolean;
    function Delete(Index: Integer): Boolean;
    procedure BeginWalk;
    procedure BeginWalkEnd;
    function Walk(var Data: Pointer): Boolean;
    function WalkBack(var Data: Pointer): Boolean;
    function GetCurrent(var Data: Pointer): Boolean;
    function SetCurrent(Data: Pointer): Boolean;
    function IndexOf(Data: Pointer): Integer;
  end;

{ ****************************************************************************
  * TList                                                                   *
  **************************************************************************** }

constructor TList.Create;
begin
  inherited Create;
  FStart := nil;
  FEnd := nil;
  FCount := 0;
  FCurrent := nil;
end;

destructor TList.Destroy;
begin
  try
    Clear;
  finally
    inherited Destroy;
  end;
end;

procedure TList.Clear;
var
  Current: PListItem;
  Next: PListItem;
begin
  Current := FStart;
  while Current <> nil do begin
    Next := Current^.Next;
    try
      Dispose(Current);
    finally
      Current := Next;
    end;
  end;
  FStart := nil;
  FEnd := nil;
  FCount := 0;
  FCurrent := nil;
end;

procedure TList.Add(Data: Pointer);
var
  item: PListItem;
begin
  New(item);
  item^.Data := Data;
  if (FEnd = nil) or (FStart = nil) then begin
    item^.Prev := nil;
    item^.Next := nil;
    FStart := item;
    FEnd := item;
  end else begin
    FEnd^.Next := item;
    item^.Next := nil;
    item^.Prev := FEnd;
    FEnd := item;
  end;
  Inc(FCount);
end;

function TList.Count: Integer;
begin
  Result := FCount;
end;

function TList.GetItem(Index: Integer): Pointer;
var
  x: Integer;
  item: PListItem;
begin
  item := FStart;
  for x := 1 to Index do begin
    if item = nil then begin
      Break;
    end;
    item := item^.Next;
  end;
  if item = nil then begin
    Result := nil;
  end else begin
    Result := item^.Data;
  end;
end;

procedure TList.SetItem(Index: Integer; Data: Pointer);
var
  x: Integer;
  item: PListItem;
begin
  item := FStart;
  for x := 1 to Index do begin
    if item = nil then begin
      Break;
    end;
    item := item^.Next;
  end;
  if item <> nil then begin
    item^.Data := Data;
  end;
end;

function TList.Remove(Data: Pointer): Boolean;
var
  item, next: PListItem;
begin
  Result := false;
  item := FStart;
  while item <> nil do begin
    next := item^.Next;
    if item^.Data = Data then begin
      if item^.Prev <> nil then begin
        item^.Prev^.Next := next;
        if next <> nil then begin
          next^.Prev := item^.Prev;
        end else begin
          FEnd := item^.Prev;
          item^.Prev^.Next := nil;
        end;
      end else begin
        FStart := next;
        if next <> nil then begin
          next^.Prev := nil;
        end else begin
          FEnd := item;
        end;
      end;
      try
        Dec(FCount);
        if item = FCurrent then begin
          if FCurrent <> nil then begin
            FCurrent := FCurrent^.Prev;
          end;
        end;
        Dispose(item);
      finally
        Result := true;
      end;
      Break;
    end;
    item := next;
  end;
end;

function TList.Delete(Index: Integer): Boolean;
var
  item, next: PListItem;
  x: Integer;
begin
  Result := false;
  item := FStart;
  x := 0;
  while (item <> nil) and (x <= Index) do begin
    next := item^.Next;
    if x = Index then begin
      if item^.Prev <> nil then begin
        item^.Prev^.Next := next;
        if next <> nil then begin
          next^.Prev := item^.Prev;
        end else begin
          FEnd := item^.Prev;
          item^.Prev^.Next := nil;
        end;
      end else begin
        FStart := next;
        if next <> nil then begin
          next^.Prev := nil;
        end else begin
          FEnd := item;
        end;
      end;
      try
        Dec(FCount);
        if item = FCurrent then begin
          if FCurrent <> nil then begin
            FCurrent := FCurrent^.Prev;
          end;
        end;
        Dispose(item);
      finally
        Result := true;
      end;
      Break;
    end;
    item := next;
    Inc(x);
  end;
end;

procedure TList.BeginWalk;
begin
  FCurrent := FStart;
end;

procedure TList.BeginWalkEnd;
begin
  FCurrent := FEnd;
end;

function TList.Walk(var Data: Pointer): Boolean;
begin
  Result := FCurrent <> nil;
  if Result then begin
    Data := FCurrent^.Data;
    FCurrent := FCurrent^.Next;
  end;
end;

function TList.WalkBack(var Data: Pointer): Boolean;
begin
  Result := FCurrent <> nil;
  if Result then begin
    Data := FCurrent^.Data;
    FCurrent := FCurrent^.Prev;
  end;
end;

function TList.GetCurrent(var Data: Pointer): Boolean;
begin
  Result := FCurrent <> nil;
  if Result then begin
    Result := FCurrent^.Prev <> nil;
    if Result then begin
      Data := FCurrent^.Prev^.Data;
    end else begin
      Data := FCurrent^.Data;
    end;
  end;
end;

function TList.SetCurrent(Data: Pointer): Boolean;
begin
  Result := FCurrent <> nil;
  if Result then begin
    Result := FCurrent^.Prev <> nil;
    if Result then begin
      FCurrent^.Prev^.Data := Data;
    end else begin
      FCurrent^.Data := Data;
    end;
  end;
end;

function TList.IndexOf(Data: Pointer): Integer;
var
  item: PListItem;
  x: Integer;
begin
  Result := -1;
  x := 0;
  item := FStart;
  while item <> nil do begin
    if item^.Data = Data then begin
      Result := x;
      Break;
    end;
    Inc(x);
    item := item^.Next;
  end;
end;
[edit=Luckie]Wir haben Delphi-Tags. :zwinker: Mfg, Luckie[/edit]

Luckie 20. Dez 2003 23:40

Re: Dynamische Arrays "zu Fuß"
 
Danke dir, aber ich werde mit der TList aus Classes schon klar kommen.

Was macht eigentlich die Methode Walk?

w3seek 20. Dez 2003 23:44

Re: Dynamische Arrays "zu Fuß"
 
die kann man verwenden wenn man einfach alle eintraege der TList durchlaufen will bis zum Ende

Luckie 20. Dez 2003 23:45

Re: Dynamische Arrays "zu Fuß"
 
Hm. Dann hätte ich aber BeginWalk und BeginEndWalk private gemacht.

w3seek 20. Dez 2003 23:49

Re: Dynamische Arrays "zu Fuß"
 
nope, sonst kann man sie ja nicht verwenden wenn die klasse in einer anderen unit ist ;)

Luckie 20. Dez 2003 23:51

Re: Dynamische Arrays "zu Fuß"
 
Die Methoden setzten doch nur den Start- und Endpunkt und werden nur von der Klasse für Walk gebraucht. Aber so genau habe ich sie mir nochnicht angekuckt.

w3seek 20. Dez 2003 23:53

Re: Dynamische Arrays "zu Fuß"
 
nein das ist eher so gedacht:
Code:
List.BeginWalk
while List.Walk(item) do begin
...
end;
bzw.
Code:
List.BeginWalkEnd
while List.WalkBack(item) do begin
...
end;

scp 20. Dez 2003 23:58

Re: Dynamische Arrays "zu Fuß"
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hab mir vor kurzem auch D3Pro zugelegt und mich mit dynamischen Arrays und einer nonVCL-Alternative zu TStringList beschäftigt und bin auch zu dem Schluss gekommen mich bei der Classes.pas zu bedienen, die ja auch bei D3Pro beiliegt.

Ergebnis siehe Anhang.
Anwendungsbeispiel siehe Hier im Forum suchendfm2rc

Luckie 21. Dez 2003 02:58

Re: Dynamische Arrays "zu Fuß"
 
Gut, ich habe es mir etwas einfachher gemacht. Ich musste nur die Exceptions auskommentiren, weil die wiede rin SysUtils drin sind. Mal sehen, was ich mir da einfallen lassen kann.

Alexander 21. Dez 2003 09:22

Re: Dynamische Arrays "zu Fuß"
 
Bei der Pro-Version sind doch die Sourcen dabei, dann kannst du die doch den entsprechenden Source rauskopieren.

Edit: Ups... Habe die 2. Seite übersehen...

choose 21. Dez 2003 10:38

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von w3seek
nein das ist eher so gedacht:
Code:
List.BeginWalk
while List.Walk(item) do begin
...
end;
bzw.
Code:
List.BeginWalkEnd
while List.WalkBack(item) do begin
...
end;

Hallo w3seek,

kannst Du mir kurz zeigen, wie Du mit diesem internen Iterator etwas in der Art
Delphi-Quellcode:
for i:=0 to High(myArary)-1 do
  for a:= i to High(myArray) do
    doSth(myArray[i], myArray[a]);
hinbekommst?

Darüber hinaus sind solche Zustandsbehaftete interne Interatoren problematisch bei Threads...

w3seek 21. Dez 2003 11:16

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

kannst Du mir kurz zeigen, wie Du mit diesem internen Iterator etwas in der Art
Delphi-Quellcode:
for i:=0 to High(myArary)-1 do
  for a:= i to High(myArray) do
    doSth(myArray[i], myArray[a]);
hinbekommst?
Delphi-Quellcode:
list.BeginWalk;
while list.Walk(sublist) do begin
  sublist.BeginWalk;
  while sublist.Walk(entry) do
    doSth(sublist, entry);
  end;
end;
ist zwar nicht 100% das selbe aber es handelt sich wie gesagt um eine verkettete liste und ist deshalb nicht direkt vergleichbar mit einm array.

Zitat:

Darüber hinaus sind solche Zustandsbehaftete interne Interatoren problematisch bei Threads...
Ich hatte niemals behauptet dass diese Liste thread-sicher waere, ist die TList und statische/dynamische arrays im uebrigen auch nicht. Der unterschied ist nur dass TList und statische/dynamische arrays beim reinen lesen von Eintraegen thread-sicher ist und meine nicht. Es kommt halt darauf an fuer was man es einsetzt, fuer mein damaliges projekt hatte diese variante eben gereicht und ich hab mir gedacht kann ich ja mal posten weils zum thema passt...

choose 21. Dez 2003 11:46

Re: Dynamische Arrays "zu Fuß"
 
Die SubList muss ich wohl übersehen haben... Und muss man dieses Exemplar dann nicht wieder freigeben?
Ich wollte nicht behaupten, dass Arrays threadsafe sind, aber sie sind, im Gegensatz zu einem zustandsbehafteten internen Iterator, immerhin treadable. Falls Dich das Thema interessiert, sieh Dir mal das Bei Google sucheniterator pattern (GoF) an, bei dem beliebig viele externe Iteratoren mit ihren unabhängigigen Stati und einer Referenz auf die zu iterierene Liste gehalten werden können...
Eine Lösung könnte dann zB so aussehen (wenn die Iteratoren mit einer Referenzzählung ausgestattet sind)
Delphi-Quellcode:
with myList.Iterator do
  while HasNext do
    DoSth(Next);
bzw
Delphi-Quellcode:
with myList.Iterator do
  with HasNext do
  begin
    myItem:= Next;
    with myList.Iterator(myItem) do
      while HasNext do
        DoSth(myItem, Next);
  end;

w3seek 21. Dez 2003 11:54

Re: Dynamische Arrays "zu Fuß"
 
da ich mich mit win32 kernel mode programmierung relativ gut auskenne, weiss ich auch wie man thread-safe code schreibt ;) Wie gesagt das war nicht das Ziel meiner implementierung damals. Es hatte fuer meine Zwecke gereicht.

w3seek 21. Dez 2003 12:01

Re: Dynamische Arrays "zu Fuß"
 
am besten sind immer noch die doppelt verketteten listen, wenn auch nicht threadsafe...

choose 21. Dez 2003 12:07

Re: Dynamische Arrays "zu Fuß"
 
Das kommt immer auf die Anwendung an, ich bin ebenfalls ein Fan von Hashtables und Skiplisten und für suchen in Strukturen natürlich Bäumen...
Bei dem von Luckie skizzierten Anwendungsfall, nämlich einem Ersatz für dynamische Arrays, halte ich aber alles, was über eine Lösung der Art
Delphi-Quellcode:
myArray^[n]:= MyTypeCheckedVar;
hinausgeht, für maßlos übertrieben.

jbg 21. Dez 2003 12:30

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von Nailor
Aber falls du die D3Prof-Version hättest, könntest du den TList Code rauskopieren, und kämst auf unter 130 KB...

Dazu sagt die Borland Lizenz:
Zitat:

[...] Unabhängig von allen
Änderungen, die Sie vornehmen, dürfen Sie keine Dateien
verteilen (insbesondere keinen Borland-Quellcode und andere
nicht compilierte Dateien), außer denen, die Borland
explizit als weitergabefähige Dateien gekennzeichnet hat.
Also nichts mit OpenSource.

vbinsider 26. Dez 2003 22:45

Re: Dynamische Arrays "zu Fuß"
 
aber du gibst ja nicht den Quellcode von der TList-Definition weiter, du kompilierst sie ja in dein Prog.
Also hast du doch eigentlich kein Prob mit dem Copyright

mfg

vbinsider

Chewie 27. Dez 2003 11:48

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von vbinsider
aber du gibst ja nicht den Quellcode von der TList-Definition weiter, du kompilierst sie ja in dein Prog.
Also hast du doch eigentlich kein Prob mit dem Copyright

Doch, weil Luckie seine Programme i.d.R. OpenSource veröffentlicht. Und wenn er zwecks Größenersparnis den Code von TList aus der Unit in eine eigene rauskopiert, muss er diese mitgeben, damit das Programm kompiliert werden kann.

vbinsider 28. Dez 2003 17:52

Re: Dynamische Arrays "zu Fuß"
 
Zitat:

Zitat von Chewie
Und wenn er zwecks Größenersparnis den Code von TList aus der Unit in eine eigene rauskopiert, muss er diese mitgeben, damit das Programm kompiliert werden kann.

eigentlich nicht, auch bei vielen Progs im Netz ist es so, dass einfach nur die DCU mitgeliefert wird. Die kann man nicht mehr dekompilieren. So gibt man nicht den Quellcode weiter, sondern nur das Kompilat.
Wenn man das Copyright nun genau interpretiert, so dürfte das keine Verletzung darstellen.

Luckie 28. Dez 2003 21:57

Re: Dynamische Arrays "zu Fuß"
 
Und was solldas bringen, bei OpenSource die Kompilate weiterzugeben? das kan ich mir dann ja auch sparen. Aber davon mal abgesehen, mit der Prof werde ich bestimmt kein OpenSource machen. :wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz