mORMot2 DailyDaily read of upstream commits

Thread wake-up goes lockless, and two API moves worth grepping for

Today is mostly about the asynchronous server core. The thread-wakeup path used by every async HTTP, WebSocket and TFTP server drops its lock in favour of two atomic counters, which should show up as less contention on busy multi-core boxes. One smaller change is worth a grep through your own code: the mORMot 1 compatibility function Lecuyer moved to another unit. TOrmTable.GetAsVariant and ToDocVariant also swapped an out parameter for var, with no consequence for callers. Everything else is internal cleanup.

TL;DR

  • Async server thread wake-up is now lockless: two CAS counters replace the TLightLock that guarded acoThreadSmooting.
  • TOrmTable.GetAsVariant and ToDocVariant went from out to var: no caller-visible change, one compiler finalization less per call.
  • The legacy Lecuyer function moved from mormot.core.base to mormot.crypt.core and now returns the shared ThreadRandom generator.
  • TLoggedThread gained an ExecuteDone property, standing in for the RTL Finished property on older compilers.
  • The TFTP server compiles again on Delphi 7 and 2007 after last week's worker-lifetime fix.

Upgrade advice

Nothing here forces an emergency upgrade. If you run async servers under load, this batch is worth pulling for the wake-up path alone — check the Lecuyer note first, since a unit move can compile differently in your tree than it does upstream. If you build with PUREMORMOT2, the Lecuyer removal is a no-op for you.

Build2.4.16604 → 2.4.16618
Commits11
Lines+467 -280
Read4 min

9 of 9 entries · 11 commits upstream

Stories
# Entry Category Units
1 Medium Async server thread wake-up drops its lock for atomic counters mormot.core.base gains LockedGet32(Target: PInteger), an atomic read-and-reset built on LockedExc32. mormot.net.async then replaces the fThreadPollingWakeupSafe TLightLock with two cardinal CAS counters, fWakeupOne and fWakeupEvents, and reads them through LockedGet32 inside ThreadPollingWakeupOne and ThreadPollingWakeupEvents. About 250 lines of the wake-up path were reshuffled around those counters. Performance mormot.core.base+1 73cb9543+150-116

core: new LockedGet32() wrapper function

Impact

No API change for application code. On a busy async HTTP or WebSocket server with acoThreadSmooting enabled, threads no longer serialise on a lock to decide who wakes up, so wake-up latency should flatten out under contention. The effect grows with core count and connection churn; a lightly loaded server will not notice.

Public API

  • LockedGet32(Target: PInteger): integeradded — Atomic 'read then zero' on a 32-bit value, in mormot.core.base.

Arnaud Bouchez · 12:03 UTC · view the commit on GitHub →

2 Medium TFTP server builds again on Delphi 7 and 2007 The TTftpConnectionThread.HasFinished helper introduced by pull request #556 relied on the RTL Finished property, which does not exist on Delphi 7 and 2007. It was removed and replaced by the new TLoggedThread.ExecuteDone property, and the shutdown loop that terminated each worker was simplified at the same time. Compiler & platform mormot.net.tftp.server 0acf8522+19-25

net: fixed TFTP server compilation under Delphi 7/2007 - after #556 fix

Impact

If you build the TFTP server on an old Delphi, it compiles again. Everyone else gets the same behaviour through a different property. This is the compatibility follow-up to the worker-lifetime fix merged earlier today.

Arnaud Bouchez · 07:42 UTC · PR #556 · view the commit on GitHub →

3 Medium The legacy Lecuyer function moved out of mormot.core.base The mORMot 1 compatibility function Lecuyer and its _Lecuyer threadvar were removed from mormot.core.base and re-declared in mormot.crypt.core, where the function now simply returns ThreadRandom. As before, the whole thing is compiled out under PUREMORMOT2. This unblocks compilation in PUREMORMOT2 mode, which the previous refactoring had broken. Compiler & platform mormot.core.base+1 fdb5f378+14-28

crypt: fixed compilation in PUREMORMOT2 mode - the Lecuyer function should move to mormot.crypt.core and use the better RandomLecuyer() factory

Impact

Code still calling Lecuyer — typically old mORMot 1 code — now needs mormot.crypt.core in its uses clause instead of relying on mormot.core.base, and shares the ThreadRandom generator rather than its own threadvar. If you already build with PUREMORMOT2 the symbol never existed for you and nothing changes.

Worth a look

Grep for 'Lecuyer' outside the framework. Where it appears, add mormot.crypt.core to the uses clause, or switch to ThreadRandom / RandomLecuyer directly.

Public API

  • Lecuyer: PLecuyerrenamed — Same name, different unit: mormot.core.base -> mormot.crypt.core.

Arnaud Bouchez · 06:28 UTC · view the commit on GitHub →

4 Low New ShortStringToVariant helper for UTF-8 short strings mormot.core.base adds ShortStringToVariant(const Txt: ShortString; var Value: variant), an inlined wrapper over RawUtf8ToVariant that produces a varString RawUtf8 variant from a UTF-8 encoded ShortString. New features mormot.core.base a4bad08e+11-2

core: new ShortStringToVariant() function

Impact

Additive convenience, used internally by today's ORM variant work. Nothing to change in existing code; it saves a manual conversion if you convert ShortStrings to variants yourself.

Public API

  • ShortStringToVariant(const Txt: ShortString; var Value: variant)added

Arnaud Bouchez · 07:41 UTC · view the commit on GitHub →

5 Low TLoggedThread can now tell you its Execute has finished mormot.core.threads adds a private fExecuteDone flag, set once the thread body returns, exposed as the read-only ExecuteDone property on TLoggedThread. The comment says it mimics the Finished property of newer Delphi and FPC runtimes. New features mormot.core.threads e42d4a3c+7-3

core: new TLoggedThread.ExecuteDone property

Impact

Useful when you shut a pool of worker threads down and need to know which ones are really out of Execute, on compilers whose RTL has no Finished property. Purely additive: existing code is unaffected.

Public API

  • TLoggedThread.ExecuteDone: booleanadded — Read-only, set when Execute returns.

Arnaud Bouchez · 07:42 UTC · view the commit on GitHub →

6 Low TOrmTable variant getters shed a redundant clear at the call site TOrmTableAbstract.GetAsVariant and TOrmTableAbstract.ToDocVariant changed their destination parameter from 'out value: variant' to 'var value: variant', and the time-field conversion moved into a new ValueVarTimeAsText helper that fills the variant in place. The body still clears the destination itself — VarClearAndSetType(value, varNull) is the first statement of GetAsVariant — so all the change removes is the finalization the compiler inserted at every call site. Performance mormot.orm.base 5530a593+69-59

orm: optimize TOrmTable variant generation

Impact

No change for callers. Because the function clears the destination on entry, a variant you pass in cannot carry stale content and nothing leaks. What disappears is one compiler-inserted finalization per call, which is where the speed-up comes from when walking a large result set row by row. Recompiling is enough.

Public API

  • TOrmTableAbstract.GetAsVariant(row, field: PtrInt; var value: variant; ...)signature-changed — out -> var; the function clears the destination itself, so callers are unaffected.
  • TOrmTableAbstract.ToDocVariant(Row: PtrInt; var doc: variant; ...)signature-changed — out -> var; the function clears the destination itself, so callers are unaffected.

Arnaud Bouchez · 06:52 UTC · view the commit on GitHub →

7 Low Wake-up rewrite finished, with inlining made conditional again The finishing commit of the lockless wake-up work. ThreadPollingWakeupOne keeps its inline directive but behind {$ifdef HASINLINE}, ThreadPollingWakeupEvents loses inlining altogether, and the comment describing when a thread is woken was rewritten to mention slow REST processing next to accept() on an idle server. Performance mormot.net.async 4c702f55+5-5

net: new lockless acoThreadSmooting implementation - use two CAS counters to avoid spinning on contention during thread wakeup

Impact

No behaviour change for application code. The conditional inline matters only if you build with a compiler that has no inlining support, where the previous commit would not have compiled.

Arnaud Bouchez · 12:08 UTC · view the commit on GitHub →

8 Low ORM temp variants switch to TSynVarData and standard VarClear Several ORM helpers that used a raw TVarData scratch value now use TSynVarData, set VType directly instead of poking through PCardinal, and release it with VarClear(variant(value)) rather than calling VarClearProc. Same code paths, clearer and less pointer-cast-heavy. Under the hood mormot.orm.base 7813f048+14-14

orm: some refactoring about variant values

Impact

No impact on application code: these are local temporaries inside the ORM. Worth knowing only if you maintain a patch against these units, where it will conflict.

Arnaud Bouchez · 07:14 UTC · view the commit on GitHub →

9 Low TFTP server test coverage extended around the #556 fix test.net.proto exercises the TFTP server more thoroughly after the worker-lifetime pull request, checking connection shutdown rather than only the happy path. Tests ca302d17+14-8

tests: better TFTP server coverage - refactored #556 pull request

Impact

No impact on application code. It makes the regression suite more likely to catch a future break in TFTP worker shutdown.

Arnaud Bouchez · 07:43 UTC · PR #556 · view the commit on GitHub →

Upstream activity commits per day · last 60 days
Commits977
Active days44/60
Busiest2026-09-30
Peak60
2026-08-15: 0 commits2026-08-16: 0 commits2026-08-17: 0 commits2026-08-18: 0 commits2026-08-19: 0 commits2026-08-20: 0 commits2026-08-21: 0 commits2026-08-22: 0 commits2026-08-23: 0 commits2026-08-24: 0 commits2026-08-25: 0 commits2026-08-26: 0 commits2026-08-27: 26 commits2026-08-28: 11 commits2026-08-29: 10 commits2026-08-30: 1 commit2026-08-31: 23 commits2026-09-01: 0 commits2026-09-02: 20 commits2026-09-03: 29 commits2026-09-04: 35 commits2026-09-05: 13 commits2026-09-06: 0 commits2026-09-07: 0 commits2026-09-08: 23 commits2026-09-09: 10 commits2026-09-10: 17 commits2026-09-11: 23 commits2026-09-12: 14 commits2026-09-13: 9 commits2026-09-14: 7 commits2026-09-15: 4 commits2026-09-16: 24 commits2026-09-17: 26 commits2026-09-18: 21 commits2026-09-19: 59 commits2026-09-20: 13 commits2026-09-21: 5 commits2026-09-22: 34 commits2026-09-23: 17 commits2026-09-24: 57 commits2026-09-25: 22 commits2026-09-26: 26 commits2026-09-27: 0 commits2026-09-28: 2 commits2026-09-29: 19 commits2026-09-30: 60 commits2026-10-01: 26 commits2026-10-02: 30 commits2026-10-03: 32 commits2026-10-04: 15 commits2026-10-05: 1 commit2026-10-06: 26 commits2026-10-07: 37 commits2026-10-08: 27 commits2026-10-09: 35 commits2026-10-10: 33 commits2026-10-11: 9 commits2026-10-12: 11 commits2026-10-13: 35 commits
2026-08-152026-10-13