Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-05

Example requested for TList and Sort using data type of Object (or record).

17 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Peter Williams

Hi all,

I have been googling without success looking for Lazarus TList examples using the Sort procedure. I want to use a TObject or Record data type.

Does anyone here know of any examples of this (TList, Sort and Object or Record data types) ? I realize that I need to write my own compare procedure and I don't have a problem with this (in theory :-).

I would appreciate a link to some pasted code in http://pastebin.com -- if you can supply it. Or a url to a webpage about this.

nb - I have no preference for using or not using Generic or Specialize keywords. I just want something that works.

Best Regards,
Peter

Reply by email

Mattias Gaertner
to Peter Williams: I have been googling without success looking for Lazarus TList examples using the Sort…
Show quoted text 15 lines
Hi all, I have been googling without success looking for Lazarus TList examples using the Sort procedure. I want to use a TObject or Record data type. Does anyone here know of any examples of this (TList, Sort and Object or Record data types) ? I realize that I need to write my own compare procedure and I don't have a problem with this (in theory :-). I would appreciate a link to some pasted code in http://pastebin.com -- if you can supply it. Or a url to a webpage about this. nb - I have no preference for using or not using Generic or Specialize keywords. I just want something that works.
function SortComponentsForName(Item1, Item2: Pointer): integer;
var
  Comp1: TComponent absolute Item1;
  Comp2: TComponent absolute Item2;
begin
  Result:=CompareText(Comp1.Name,Comp2.Name);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
  l: TList;
begin
  l:=TList.Create;
  l.Add(Button2);
  l.Add(Button1);
  l.Sort(@SortComponentsForName);
end;

Mattias

Reply by email

Marcos Douglas
to Mattias Gaertner
Mattias Gaertner wrote 8 lines
function SortComponentsForName(Item1, Item2: Pointer): integer; var ?Comp1: TComponent absolute Item1; ?Comp2: TComponent absolute Item2; begin ?Result:=CompareText(Comp1.Name,Comp2.Name); end;

I did not know about 'absolute' yet... what is the vantage? Can you give me a link about it, please?

Marcos Douglas

Reply by email

Sven Barth
to Marcos Douglas: On Wed, May 11, 2011 at 3:51 AM, Mattias Gaertner I did not know about 'absolute' yet...…
Marcos Douglas wrote 13 lines
On Wed, May 11, 2011 at 3:51 AM, Mattias Gaertner wrote: > > function SortComponentsForName(Item1, Item2: Pointer): integer; > var > Comp1: TComponent absolute Item1; > Comp2: TComponent absolute Item2; > begin > Result:=CompareText(Comp1.Name,Comp2.Name); > end; I did not know about 'absolute' yet... what is the vantage? Can you give me a link about it, please?

See here (in the list point 6):
http://freepascal.org/docs-html/ref/refse20.html#x52-590004.2

It allows you to declare a variable that has the same location as another variable or parameter (but it does not need to have the same type). In the example written by Matthias Comp1 contains the value of Item1 from the "begin" on. The other way to achive this is the following:

function SortComponentsForName(Item1, Item2: Pointer): Integer;
var
   Comp1, Comp2: TComponent;
begin
   Comp1 := TComponent(Item1);
   Comp2 := TComponent(Item2);
   Result := CompareText(Comp1.Name, Comp2.Name);
end;

Regards,
Sven

Reply by email

Marcos Douglas
to Sven Barth: See here (in the list point 6): http://freepascal.org/docs-html/ref/refse20.html#x52-59000…
Sven Barth wrote 32 lines
Am 11.05.2011 14:30, schrieb Marcos Douglas: > > On Wed, May 11, 2011 at 3:51 AM, Mattias Gaertner > ?wrote: >> >> function SortComponentsForName(Item1, Item2: Pointer): integer; >> var >> ?Comp1: TComponent absolute Item1; >> ?Comp2: TComponent absolute Item2; >> begin >> ?Result:=CompareText(Comp1.Name,Comp2.Name); >> end; > > I did not know about 'absolute' yet... what is the vantage? > Can you give me a link about it, please? See here (in the list point 6): http://freepascal.org/docs-html/ref/refse20.html#x52-590004.2 It allows you to declare a variable that has the same location as another variable or parameter (but it does not need to have the same type). In the example written by Matthias Comp1 contains the value of Item1 from the "begin" on. The other way to achive this is the following: function SortComponentsForName(Item1, Item2: Pointer): Integer; var ?Comp1, Comp2: TComponent; begin ?Comp1 := TComponent(Item1); ?Comp2 := TComponent(Item2); ?Result := CompareText(Comp1.Name, Comp2.Name); end;

OK... and an Exception occur if the conversion fail? I always use the other way, ie, type-conversion... but thanks.

Marcos Douglas

Reply by email

Sven Barth
to Marcos Douglas
Marcos Douglas wrote 36 lines
On Wed, May 11, 2011 at 9:35 AM, Sven Barth wrote: > Am 11.05.2011 14:30, schrieb Marcos Douglas: >> >> On Wed, May 11, 2011 at 3:51 AM, Mattias Gaertner >> wrote: >>> >>> function SortComponentsForName(Item1, Item2: Pointer): integer; >>> var >>> Comp1: TComponent absolute Item1; >>> Comp2: TComponent absolute Item2; >>> begin >>> Result:=CompareText(Comp1.Name,Comp2.Name); >>> end; >> >> I did not know about 'absolute' yet... what is the vantage? >> Can you give me a link about it, please? > > See here (in the list point 6): > http://freepascal.org/docs-html/ref/refse20.html#x52-590004.2 > > It allows you to declare a variable that has the same location as another > variable or parameter (but it does not need to have the same type). In the > example written by Matthias Comp1 contains the value of Item1 from the > "begin" on. The other way to achive this is the following: > > function SortComponentsForName(Item1, Item2: Pointer): Integer; > var > Comp1, Comp2: TComponent; > begin > Comp1 := TComponent(Item1); > Comp2 := TComponent(Item2); > Result := CompareText(Comp1.Name, Comp2.Name); > end; OK... and an Exception occur if the conversion fail? I always use the other way, ie, type-conversion... but thanks.

There won't be an exception as a result of the conversion (because there is none), but maybe nasty exceptions or side effects later on.

For example:

type
   TTest1 = record
     i: LongInt;
   end;
   TTest2 = record
     q: Int64;
   end;
procedure Foo;
var
   t1: TTest1;
   t2: TTest2 absolute t1;
begin
   ...
end;

As you see TTest2 is larger than TTest1, so depending on the circumstances of the run you might trigger an access violation or you might corrupt data on the stack.

If you use absolute with classes that don't inherit from another then
you can get the same nasty results if you do a normal cast between them.

Basically you need to know what you do.

Note: The following works as well and can be used as a safety measure in case of classes:

procedure Bar(a: TObject);
var
   b: TComponent absolute a;
begin
   if a is TComponent then
     b.SomeMethodOfTComponent;
end;

Regards,
Sven

Reply by email

Sven Barth
to Michael Schnell: AFAIK, "absolute" is depreciated. You can always use type-conversion on pointers for this.
Michael Schnell wrote 6 lines
On 05/11/2011 02:30 PM, Marcos Douglas wrote: > > I did not know about 'absolute' yet... what is the vantage? > Can you give me a link about it, please? > AFAIK, "absolute" is depreciated.

That's news to me... it might be in Delphi, but not in FPC.

You can always use type-conversion on pointers for this.

Regards,
Sven

Reply by email

Graeme Geldenhuys
to Sven Barth: See here (in the list point 6): http://freepascal.org/docs-html/ref/refse20.html#x52-59000…
Sven Barth wrote 6 lines
function SortComponentsForName(Item1, Item2: Pointer): Integer; var ?Comp1, Comp2: TComponent; begin ?Comp1 := TComponent(Item1); ?Comp2 := TComponent(Item2);

This is what I have always been using.... Is one method more efficient (generated code) than the other?

Regards, ? - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Sven Barth
to Graeme Geldenhuys
Graeme Geldenhuys wrote 11 lines
On 11 May 2011 14:35, Sven Barth<pascaldragon at goo*****> wrote: > function SortComponentsForName(Item1, Item2: Pointer): Integer; > var > Comp1, Comp2: TComponent; > begin > Comp1 := TComponent(Item1); > Comp2 := TComponent(Item2); This is what I have always been using.... Is one method more efficient (generated code) than the other?

The "absolute" version needs (in the example) 2 * SizeOf(Pointer) less stack space and also the two assignments aren't needed.

Example:

===source begin===

procedure Test1(aParam1, aParam2: Pointer);
var
   param1: TObject absolute aParam1;
   param2: TObject absolute aParam2;
begin
end;
procedure Test2(aParam1, aParam2: Pointer);
var
   param1: TObject;
   param2: TObject;
begin
   param1 := TObject(aParam1);
   param2 := TObject(aParam2);
end;

===source end===

The following code is generated on i386:

===assembler begin===

.section .text
.balign 16,0x90
.globl P$ABSOLUTETEST_TEST1$POINTER$POINTER
.type P$ABSOLUTETEST_TEST1$POINTER$POINTER, at function P$ABSOLUTETEST_TEST1$POINTER$POINTER:
.Lc1:
# Temps allocated between ebp-8 and ebp-8
# [absolutetest.pas]
# [9] begin
pushl %ebp
.Lc3:
.Lc4:
movl %esp,%ebp
.Lc5:
subl $8,%esp
# Var aParam1 located at ebp-4
# Var aParam2 located at ebp-8
movl %eax,-4(%ebp)
movl %edx,-8(%ebp)
# [10] end;
leave
ret
.Lc2:
.Le0:
.size P$ABSOLUTETEST_TEST1$POINTER$POINTER, .Le0 - P$ABSOLUTETEST_TEST1$POINTER$POINTER

.section .text
.balign 16,0x90
.globl P$ABSOLUTETEST_TEST2$POINTER$POINTER
.type P$ABSOLUTETEST_TEST2$POINTER$POINTER, at function P$ABSOLUTETEST_TEST2$POINTER$POINTER:
.Lc6:
# Temps allocated between ebp-16 and ebp-16
# [16] begin
pushl %ebp
.Lc8:
.Lc9:
movl %esp,%ebp
.Lc10:
subl $16,%esp
# Var aParam1 located at ebp-4
# Var aParam2 located at ebp-8
# Var param1 located at ebp-12
# Var param2 located at ebp-16
movl %eax,-4(%ebp)
movl %edx,-8(%ebp)
# [17] param1 := TObject(aParam1);
movl -4(%ebp),%eax
movl %eax,-12(%ebp)
# [18] param2 := TObject(aParam2);
movl -8(%ebp),%eax
movl %eax,-16(%ebp)
# [19] end;
leave
ret
.Lc7:
.Le1:
.size P$ABSOLUTETEST_TEST2$POINTER$POINTER, .Le1 - P$ABSOLUTETEST_TEST2$POINTER$POINTER

===assembler end===

Regards,
Sven

Reply by email

Graeme Geldenhuys
to Sven Barth
Earlier Sven Barth wrote
The "absolute" version needs (in the example) 2 * SizeOf(Pointer) less stack space and also the two assignments aren't needed.

Thanks for that. I guess I need to start using this language feature then. I'm all for optimizations - every cpu cycle counts. :-)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Sven Barth
to Michael Schnell
Michael Schnell wrote
With components, maybe "as" is even more decent. it will generate even more overhead, but do a type check for safety.

If you get pointers passed in (which is the case in TList's Sort handler) then you need to do a unsafe typecast at least to TObject anyway, so you're able to use "as" at all.

Regards,
Sven

Reply by email

Sven Barth
to Graeme Geldenhuys: Thanks for that. I guess I need to start using this language feature then. I'm all for…
Graeme Geldenhuys wrote 7 lines
Earlier Sven Barth wrote: > > The "absolute" version needs (in the example) 2 * SizeOf(Pointer) > less stack space and also the two assignments aren't needed. Thanks for that. I guess I need to start using this language feature then. I'm all for optimizations - every cpu cycle counts. :-)

If you use a method/function often that could indeed pay off.

What I don't know is whether one of FPC's optimization steps solves this already (I have tested without optimization).

Regards,
Sven

Reply by email

Graeme Geldenhuys
to Sven Barth
Sven Barth wrote
What I don't know is whether one of FPC's optimization steps solves this already (I have tested without optimization).

Interesting question. I guess we will just have to wait for Michael van Canneyt's "Code Optimization with FPC" book to be released. ;-)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email