FredS
Members-
Content Count
418 -
Joined
-
Last visited
-
Days Won
4
Everything posted by FredS
-
@Attila Kovacs Doubt that is possible, I imagine that you need to prep your new string in a function then write it out.
-
Yes, ends with "One Million Two Thousand and 34/100"
-
Been on the back of my mind since I read Marco's book but I never had to deal with strings where a lock wasn't used. However, if the main thread (mt) only reads and a worker thread (wt) only writes this should be fine. The way I see this is that when the wt writes to a string variable if first makes a reference copy of the original. If the mt reads that string it gets the old value while its being written to. Once the write lock is off the string var now points to the new string and when the mt tries to read it the next time around it gets a reference to that string. A quick test is below, I used a Cursive Number method to make the string more complex for the test, I know a version of that is available here somewhere. Unfortunately the version available does not reverse from Text. But you can simply replace these three calls with CurrToStr/StrToCurr. Guess I could let that run a bit longer and see if there are any collisions.. //MMWIN:MEMBERSCOPY unit _MM_Copy_Buffer_; interface type THelperTests = class(TObject) public [Test] [TestCase('10k', '10000')] procedure TestStringThreadSafe(Iterations: Integer); end; implementation procedure THelperTests.TestStringThreadSafe(Iterations: Integer); var c, LastReadC : Currency; s : string; HasTerminated : Boolean; i : integer; const IncBy = 1000; begin // Assert.IsTrue(TAtomic.IsNatural(c, SizeOf(c)), 'Currency will only work in x64'); c := 1000.34; s := TCursiveNumbers.ToText(c); {- Reading } TThread.CreateAnonymousThread( procedure var rS : string; CurrentC : Currency; begin LastReadC := c; rS := s; while not HasTerminated do if rS <> S then begin rS := S; CurrentC := TCursiveNumbers.ToCurrency(rS); Assert.AreEqual(LastReadC + IncBy, CurrentC, 'Oops'); LastReadC := CurrentC; end; end).Start; for i := 0 to Iterations do begin c := c + IncBy; s := TCursiveNumbers.ToText(c); Sleep(1); // give the slice away end; HasTerminated := True; Sleep(2); Assert.AreEqual(c, LastReadC, 'Reading does not match writing'); Log(S); end; end.
-
Was that a typo?
-
And Tokyo was much worse than Berlin 🙂
-
OK, simple variables and lets add default aligned, but that was not the question. As you can see with the TSrwLock declaration, the FIRST variable in a record is always properly aligned. I use this during initialization: //MMWIN:MEMBERSCOPY unit _MM_Copy_Buffer_; interface type TAtomic = record /// <summary> /// Assures {$A8} or {$A+} state /// </summary> /// <seealso href="https://stackoverflow.com/questions/829235/ifopt-a4"> /// {$IFOPT A4}? /// </seealso> class constructor Create; end; implementation { TAtomic } class constructor TAtomic.Create; type TTestRec = record A: Byte; B: Int64; end; begin // In the {$A8} or {$A+} state, fields in record types that are declared without the packed modifier and fields in class structures are aligned on quadword boundaries. {$IF SIZEOF(TTestRec) <> 16} 'App must be compiled in A8 mode' {$IFEND} end; end.
-
Variables SizeOf Pointer or below is always atomic. Atomic means access to a full variable in one read/write.
-
I checked for installation instructions and found none, attempted an install and failed. Enough new EMB tech for now.. 🙂 BTW: Its difficult to compare previous installers since they change (and fail) frequently but in the last few ISO versions it prompted for an uninstall before installing. Will see how that goes on my laptop later, its setup using 'Web Installer'..
-
Backup first! Install attempt using `delphicbuilder10_3_3_7899_nt.iso` actually removed Rio. The first screen was kind of suspicious:
-
Which should not be required for a single privilege.
-
I was using Berlin elevated when I ran that and get the same error msg while running non elevated. My own wrapper around AdjustTokenPrivileges works because it checks the last error after that call regardless of the number of privileges adjusted. In your demo (GetLastError=1300) while running non elevated. This code behaves correctly: // Enable or disable the privilege Result := AdjustTokenPrivileges(LToken, False, LTokenPriv, SizeOf(LPrevTokenPriv), LPrevTokenPriv, LLength); Result := Result and (GetLastError = ERROR_SUCCESS);
-
Works in Berlin when I change output to an existing folder: 'd:\Notepad.dat' Plus this addition gives me the dialog below if I try to save into a dir which does not exist: ShowMessage('Could not save: ' + LReg.LastErrorMsg); [Window Title] Project1 [Content] Could not save: The system cannot find the path specified [OK]
-
Just read that on your site, sounds like a great option. As for hardware; Uwe supplied the link, a full Linux version is required (no router). I have that running but I'm thinking about hardware failure and in that case running a license server on the same machine(s) isn't optimal. I do have an Ubuntu Azure VM running and that may be the best way to do this..
-
I'm going to assume there are no Docker images nor light weight installs (for a Router) of this? This does seem to be an important change to consider, unless one believes in a flawless self updating registration system being right around the corner..
-
OK, but NOT irrelevant to the Legal License Holder..
-
Assuming this happened on Monday when you reported and not on the weekend it only took a work week 🙂
-
I have a couple of instances where this is more useful without the LookupDataset, additions below: interface type TDictionaryLookupList = class(TLookupList) public /// <summary> /// Binds a Dictionary Lookup List to a fkLookup Field /// </summary> class function Bind(const AField: TField): TLookupList; /// <summary> /// Binds a Dictionary Lookup List to a fkLookup Field without binding to a LookupDataSet /// </summary> /// <param name="AKeyFields"> /// Keyfields used to identify the Entry, (Default=EmptyStr) will use the Existing KeyFields value. /// </param> class function BindSimpleList(const AField: TField; const AKeyFields: string = ''): TLookupList; end; implementation type TFieldHelper = class helper for TField /// <summary> Sets Private Field </summary> procedure SetLookupList(ALookupList : TLookupList); end; procedure TFieldHelper.SetLookupList(ALookupList : TLookupList); begin if Assigned(LookupList) then LookupList.Free; with self do FLookupList := ALookupList; end; class function TDictionaryLookupList.Bind(const AField: TField): TLookupList; begin Assert(AField.FieldKind = fkLookup); AField.LookupCache := True; Result := TDictionaryLookupList.Create(); AField.SetLookupList(Result); end; class function TDictionaryLookupList.BindSimpleList(const AField: TField; const AKeyFields: string = ''): TLookupList; begin AField.LookupDataSet := nil; if (AKeyFields <> EmptyStr) then AField.KeyFields := AKeyFields; Result := Bind(AField); end;
-
I did and stopped due to: RSP-14723. However applying them via that dialog is inconvenient the better way is to use the 'Configuration Manager': One example is to redirect output or change configuration for an entire project group. I used this a lot for UniDAC's FastReport components to change output directories. Each time new version was made available I would simply run the 'Configuration Manager' using an altered Option Set before compiling.
-
Well, at least we all learn to enjoy xcopy again.. EMBT where upgrading is a no brainer 🙂
-
create an action aiOnIdle using the forms caption link it to the form name the update event OnIdle Then use that event as needed, beware the OnIdle event won't fire when a modal dialog is up. Unlike the TActionList.OnUpdate event this one will fire as long as the form is enabled.
-
Dunno, where is the Minimal, Reproducible Example 🙂 If it works on a Windows 10 Sandbox then the code works, all else is up to AVs and Windows security. I tried to get an API Hooking using AppInit_DLLs example to work but that fails for me even in a Windows 10 Sandbox, works in W7 though.
-
Some of Hooks-Made-Easy updated and now on GitHub.
-
Feeling ignored? That code is literally from last century and had no incling about WIN64.. Although I haven't really looked at it your changes is what I needed to change in my code. Which by the way is blocked by Delphi and is NOT a commercial solution. There has been little demand for hooks in my current project so there was no need to even look at it other than as an exercise. Another reason not to get involved here is that I and you can find the solution with very little effort, but system wide hooks in Windows 1984.. err.. 10 are not so reliable. The one place we use a hook that absolutely needs to work madCodeHook is used in a signed Driver (special certificate).
-
You need DLLs for both.
-
That was a joke. That code is from last century, any warranty has expired..