GetTickCount64 duplicate lazarus / 34-Windows ---------------------------------------------------------------------- valter.home · 2021-05-26 08:53 Hello everybody. I have a problem with GetTickCount64 that never occurred. I use it to assign a unique name to panels created at runtime, eg MyPanel + [GetTickCount.ToString]. I don't go into the details of my application because I don't think it's necessary but in general: I have some figures on the screen and each of them is associated with some panels contained in a TScrollBox (which shows only the panels associated with the selected figure). When I double click on a figure, I delete the contents of the TScrollBox and recreate the panels associated with that figure (whose data is saved on a text file). I load the contents of the file into a TStringList and use a for loop to recreate the panels. What happens is that GetTickCount always returns me the same value and therefore I am raised an exception in creating the second panel (duplicate name). But if I write something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i n:=(GetTickCount64-random(1000)).ToString; MyPanel.Name:='Panel'+n; the problem seems to be solved. So it would appear that GetTickCount64 doesn't change value as opposed to random (1000) which returns a different number. Do you have any ideas? Is there any way to somehow reset GetTickCount64? [edit] I think the only explanation is that less than a millisecond passes between each pass of the loop. ---------------------------------------------------------------------- engkin · 2021-05-26 10:41 If you don't mind being limited to Intel CPU assembly, use "CPUClocks" ---------------------------------------------------------------------- PascalDragon · 2021-05-26 11:16 Quote from: valter.home on May 26, 2021, 10:53:08 amI think the only explanation is that less than a millisecond passes between each pass of the loop. Correct, that is the likely cause. ---------------------------------------------------------------------- Josh · 2021-05-26 11:35 Maybe something similar to below a global var and a funtion using it to make sure its unique. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i //global varsvar LastTick64:qword; function UniqueTick64:string;begin  while LastTick64=GetTickCount64 do sleep(1);  LastTick64:=GetTickCount64;  Result:=inttostr(LastTick64);end; .....     n:=UniqueTick64;    MyPanel.Name:='Panel'+n; ---------------------------------------------------------------------- ccrause · 2021-05-26 11:38 Quote from: PascalDragon on May 26, 2021, 01:16:28 pmQuote from: valter.home on May 26, 2021, 10:53:08 amI think the only explanation is that less than a millisecond passes between each pass of the loop. Correct, that is the likely cause. Indeed, the resolution of GetTickCount64 is 10 to 16 milliseconds. ---------------------------------------------------------------------- creaothceann · 2021-05-26 14:05 Note that a time value does not guarantee unique IDs. Why not use a counter instead? --- Quote from: engkin on May 26, 2021, 12:41:54 pmIf you don't mind being limited to Intel CPU assembly, use "CPUClocks" "We strongly discourage using the RDTSC or RDTSCP processor instruction to directly query the TSC because you won't get reliable results on some versions of Windows, across live migrations of virtual machines, and on hardware systems without invariant or tightly synchronized TSCs." - https://docs.microsoft.com/en-us/windows/win32/sysinfo/acquiring- high-resolution-time-stamps Here's a wrapper: Code: [Select]unit U_HRT; { High-Resolution Timer ===================== Windows: "[...] a high resolution (<1us) time stamp that can be used for time-interval measurements." Notes: InitialTick may be of limited value for timekeeping over longer durations (e.g. across host computer hibernations). } interface uses SysUtils; type HRT = class private class var _InitialTick    : Int64; _InitialTime    : TDateTime; _TicksPerSecond : Int64; class function  _Get_CurrentValue : Int64;  static; class procedure _Init;                      static; // API public class function TicksToSeconds(const Value : Int64) : Double;  static; class property CurrentValue   : Int64      read _Get_CurrentValue; class property InitialTick    : Int64      read _InitialTick; class property InitialTime    : TDateTime  read _InitialTime; class property TicksPerSecond : Int64      read _TicksPerSecond; end; function Seconds_to_TDateTime(const f : Double) : TDateTime; implementation function Seconds_to_TDateTime(const f : Double) : TDateTime;  inline; begin Result := f * 1000 / MSecsPerDay;  // freepascal.org/~michael/articles/datetime/datetime.pdf end; {$ifdef Windows} function QueryPerformanceCounter  (out lpPerformanceCount : Int64) : LongBool;  external 'kernel32' name 'QueryPerformanceCounter'; function QueryPerformanceFrequency(out lpFrequency        : Int64) : LongBool;  external 'kernel32' name 'QueryPerformanceFrequency'; class function HRT._Get_CurrentValue : Int64; begin QueryPerformanceCounter(Result); end; {$endif} class procedure HRT._Init;  inline; begin {$ifdef Windows} QueryPerformanceFrequency(HRT._TicksPerSecond); {$else} //... {$endif} _InitialTick := CurrentValue; _InitialTime := Now; end; class function HRT.TicksToSeconds(const Value : Int64) : Double;  inline; begin Result := Value / TicksPerSecond; end; initialization HRT._Init; end. ---------------------------------------------------------------------- valter.home · 2021-05-26 15:01 Thank you guys, a counter might perhaps be the safest way. But I'm asking myself a question: is it mandatory to name components for components created at runtime? Because I don't really use the component name under any circumstances. Unlike the ide that assigns a sequential name to the component, at runtime the component name, if not assigned, is an empty string. Could this cause random problems in running the application? ---------------------------------------------------------------------- howardpc · 2021-05-26 16:04 Leaving a dynamically created component unnamed is not a problem (unless, of course, your app depends in some way on your components having unique names, as, for instance,  the Lazarus IDE expects). In a dynamic situation naming of components is mainly useful for debugging purposes, it is not mandatory at all. The only thing that is mandatory is if you *do* name a dynamic component it must of course be a unique name. But if it isn't unique you get an immediate exception anyway, so it is never a hidden bug waiting to bite you. ---------------------------------------------------------------------- valter.home · 2021-05-26 16:19 Thanks howardpc, your confirmation is welcome! Less unnecessary code