Recent

Author Topic: Feature Request: Threadconst  (Read 211 times)

Jens K

  • Newbie
  • Posts: 1
Feature Request: Threadconst
« on: June 04, 2026, 09:38:47 am »
Hi devs,

I'm trying to move a 285.000 line old Borland Pascal protected mode program to a more modern platform. So a Client-terminal, and a server. Converting the old Btrieve databases to SQL. All that is done in FPC and Lazarus. Very good experience!

But turning a single user program into a multi-user Session is not a small task in a program of that size, and obviously the dseg-vars and consts are something that has to be dealt with. The vars are pretty much a piece of cake, thanks to Threadvar (a genius solution). It couldn't be easier. 11/10.

Now the Consts are a different story. The mutable ones (Name : LongInt = 100;) needs to be converted to Threadvars and manually initialized, unless the initial value is 0. So I now have 70 files with a [UnitName]_InitConsts procedure, and a Consts unit with a InitAllConsts, that's called at the very start of the Session code. Now that works, but it's pretty bad:
1) Find the Mutable Consts, go through all the files and do the work to change Const to Threadvars and make the _Init procedure, and document it. Not a small task.
2) You can't use Const anymore for mutable consts. The nice functionality that Consts give you now belongs to the good old days  :-\
3) Your Vars and your Consts are now mixed together as Threadvars and only the Consts are initialized in the Init procedure, as the real Vars are initialized in the code. You have to keep track of that with comments, so you can remember which vars are initialized in the code, and which are "old" Consts converted to Threadvars. It's messy, and harder to use and maintain.

A Threadconst would make all that as simple as using Threadvar. I'm sure most people who benefit from Threadvar, in any project, could benefit from Threadconst too.

I hope you will take it into consideration. Thank you.

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Feature Request: Threadconst
« Reply #1 on: June 04, 2026, 01:41:49 pm »
1.) Have you tried the refactor options in the Lazarus IDE?
ctrl-shift-e
Replaces any references in all units of a project.
2.) Not true:{$J+/-} or {$writeableconst on/off}. This is the same as in BP7 or TP7.
3.) Since this is an option BP/TP never had, you have to touch all code anyway.  Use writeable consts and use the synchronization primitives. If the consts are declared inside the thread they are thread local anyway.
Threadvar is only for global declarations, where each thread receives its own copy. This is a common mistake. Also threadvars are unnecessary SLOW! Better to avoid them.
Variables declared inside a thread are already thread local. Typed consts are always global, but fields in a thread behave as typed consts.

See:
https://docs.freepascal.org/docs-html/ref/refse26.html

Which says the same as the above.
« Last Edit: June 04, 2026, 03:48:05 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Feature Request: Threadconst
« Reply #2 on: June 04, 2026, 02:57:21 pm »
Basically, if you turn the whole program into a thread (or e.g. a cgi), you can have as many sessions running as you like.
Only limited to available resources.

And remember: very few actually use threadvars because they are slow and usually not necessary.
Simple typed constants that need to be shared across threads can be accessed with the InterlockedXXX functions.

If you want examples, please ask.
« Last Edit: June 04, 2026, 03:12:42 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

runewalsh

  • Full Member
  • ***
  • Posts: 125
Re: Feature Request: Threadconst
« Reply #3 on: June 04, 2026, 03:44:24 pm »
Correct solution is storing all per-thread state in a “state object”, but that would require deep redesign.

Your Consts unit could be implemented like this:

Code: Pascal  [Select][+][-]
  1. unit Consts;
  2.  
  3. interface
  4.  
  5.         procedure RegisterInitConsts(initConsts: TProcedure);
  6.         procedure CallAllInitConsts;
  7.  
  8. implementation
  9.  
  10. var
  11.         initConstsList: array of TProcedure;
  12.  
  13.         procedure RegisterInitConsts(initConsts: TProcedure);
  14.         begin
  15.                 Insert(initConsts, initConstsList, High(SizeInt));
  16.         end;
  17.  
  18.         procedure CallAllInitConsts;
  19.         var
  20.                 i: SizeInt;
  21.         begin
  22.                 for i := 0 to High(initConstsList) do
  23.                         initConstsList[i];
  24.         end;
  25.  
  26. end.

All units that have “thread-local mutable constants” use Consts (from implementation to prevent circular references) and call RegisterInitConsts in their initializations, then all threads call CallAllInitConsts.

Your actual constants can be implemented like this:

Code: Pascal  [Select][+][-]
  1. type
  2.         MyConstantType = record
  3.                 a, b, c: uint32;
  4.         end;
  5.  
  6. const
  7.         MyConstantSrc: MyConstantType = (a: 1; b: 2; c: 3);
  8.  
  9. threadvar
  10.         MyConstant: MyConstantType;
  11.  
  12. procedure InitConsts;
  13. begin
  14.         MyConstant := MyConstantSrc;
  15. end;

This way, you at least still have nice const declarations.

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Feature Request: Threadconst
« Reply #4 on: June 04, 2026, 03:52:59 pm »
All units that have “thread-local mutable constants”
Such beasts do not exist, simply use a field in your TThread and initialize in the constructor.
But your solution would also work for non-class based apps.
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018