Worth a looka fix or feature you may wantTwo merge commits (pull requests #556 and #558) carry no code of their own and have no entry. Corrected on 2026-08-30: this edition first claimed the out -> var change on TOrmTable.GetAsVariant exposed callers to stale content or a leak. It does not — the function clears the destination on entry. Thanks to Arnaud Bouchez for the correction.
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.
9 of 9 entries · 11 commits upstream
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.
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.
Upgrade recommended
Only relevant if you compile mormot.net.tftp.server on Delphi 7 or 2007 — in that case take this commit together with the ExecuteDone one.
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.
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
Units
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.
Units
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.
Units
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.
Units
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.
Units
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.