Recent

Author Topic: FPC Unleashed (async/await, parallel for, match, string interpolation & more)  (Read 47443 times)

440bx

  • Hero Member
  • *****
  • Posts: 6560
@Fibonacci,

Code: Pascal  [Select][+][-]
  1. function Squared(n: Integer): Integer;
  2. begin
  3.   static base := n*n;   // computed once, on the first call
  4.   Result := base;
  5. end;
  6.  
  7. begin
  8.   WriteLn(Squared(5));  // 25
  9.   WriteLn(Squared(9));  // 25 - cached, init skipped
  10. end.
  11.  
I find that a feature that operates that way to be extremely counter-intuitive and, a downright misuse of what the persistent storage is supposed to be for, which isn't for caching values.

Another thing I find undesirable is to have hidden compiler behavior.  In your example a value set only the first time it's entered.  if the programmer wants a specific value the first time the function is entered then, the programmer should be able to rely on an invariant initial value for all static variables anywhere in the program, which is usually 0 because the static is essentially a scoped global variable and, just have a simple test, "if static_var = 0 then { set it to some value }" that's explicit which prevents another programmer being surprised by getting some unexpected value the compiler produced without his/her knowledge.

Above comments offered in the spirit of being helpful.

HTH.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fibonacci

  • Hero Member
  • *****
  • Posts: 1046
  • Behold, I bring salvation - FPC Unleashed
The opportunity to raise concerns has now passed.
FPC Unleashed: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

flowCRANE

  • Hero Member
  • *****
  • Posts: 988
Any particular reason to not support static thread variables?

P.S.: Don't rush into implementation. First, it is advisable to analyze all possible scenarios, and if you do decide to implement it, make sure to prioritize the best possible functionality, benefiting as many users as possible. I get the impression that new features are being added too quickly, without much thought.
« Last Edit: June 06, 2026, 12:01:02 pm by flowCRANE »
Lazarus 4.6 with FPC 3.2.2, Windows 11 — all 64-bit

Working solo on a top-down retro-style action/adventure game (pixel art), programming the engine from scratch, using Free Pascal and SDL3.

440bx

  • Hero Member
  • *****
  • Posts: 6560
The opportunity to raise concerns has now passed.
fair enough.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19500
  • Glad to be alive.
  • Not thread-local: all threads share one instance, you handle the locking. Use unit-level threadvar for per-thread.
No. Threadvars are way too expensive. use a record for that:
Code: Pascal  [Select][+][-]
  1. procedure threadlocalinc;
  2. var
  3.   i:integer;
  4.   tl:record staticvar:integer;end; // records are initialized, I think also if stack-allocated, not sure.
  5. begin
  6.   tl.staticvar := 0; // to be sure
  7.   for i := 0 to 999 do begin inc(tl.staticvar);writeln(tl.staticvar);end;
  8. end;
This is both threadsafe and fast because it runs fully on the thread's own stack.
Threadvars aren't very useful.

BTW I like this new static feature even if not working like the above. It makes the syntax much cleaner than messing with typed consts. Both options work very good.
« Last Edit: June 06, 2026, 03:28:39 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

Fibonacci

  • Hero Member
  • *****
  • Posts: 1046
  • Behold, I bring salvation - FPC Unleashed
Any particular reason to not support static thread variables?

A static has a single place in the whole program - single, same memory address. As for a "threadstatic" (or some other name) - we can discuss it. Let's nail down the details - behavior, mechanism - and I'll implement it.

P.S.: Don't rush into implementation. First, it is advisable to analyze all possible scenarios

I try :) This single thread is too small to discuss this many different features at once...



@440bx:

Next in line: Type() - it's a small one.



Feature: atomic

Then I have an idea I think is great - I came up with it myself, but then found out other languages have it too, of course... Everything that might be useful is already implemented somewhere: lock / synchronized / std::lock_guard / std::scoped_lock / lock & defer unlock...

FPC Unleashed version: atomic(optional args) <expr>;

Sugar for initCS + enterCS-try-finally-leaveCS-end + doneCS.

Code: Pascal  [Select][+][-]
  1. atomic inc(i);                 // lock by source location
  2. atomic(i) inc(i);              // lock by "i"
  3. atomic(i, cls) i += cls.value; // lock by multiple vars/objects
  4. atomic begin {...} end;        // <expr> can be begin-end
  5.  

atomic expands to:

1. Init CS in unit/program initialization
2. Done CS in unit/program finalization
3. atomic: enter CS -> try -> EXPRESSION -> finally -> leave CS

Instead of doing all the initialization and finalization, coming up with a name for the CS, remembering it, entering it, leaving it, and writing the try-finally - you simply call atomic. IMHO brilliant.

Thoughts?

I created a thread to discuss this specific feature: Forum: FPC Unleashed: atomic
« Last Edit: June 06, 2026, 04:41:33 pm by Fibonacci »
FPC Unleashed: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

Thaddy

  • Hero Member
  • *****
  • Posts: 19500
  • Glad to be alive.
Re: FPC Unleashed: atomic
« Reply #621 on: June 06, 2026, 04:50:11 pm »
Atomic is already the case for almost all simple vars and also covered by AtomicXXX and InterlockedXXX.
Be sure to avoid these. Some values are atomic by nature and a cs would slow them down....
Then it is "better" to use a lock prefix at most.
(An example is the static integer type  :D )
« Last Edit: June 06, 2026, 04:55:54 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

flowCRANE

  • Hero Member
  • *****
  • Posts: 988
As for a "threadstatic" (or some other name) - we can discuss it. Let's nail down the details - behavior, mechanism - and I'll implement it.

I like the threadstatic keyword — is consistent with the current language syntax.

In short, threadstatic variables should offer exactly the same capabilities as regular static variables and follow the same rules regarding declaration and initialization. What would distinguish threadstatic variables from static ones is that, instead of existing in the data segment of the process (one per program), each threadstatic variable would exist in Thread-Local Storage (TLS), meaning each worker would have its own instance, access to which in multithreaded programs would not require blocking.

Any contraindications?
Lazarus 4.6 with FPC 3.2.2, Windows 11 — all 64-bit

Working solo on a top-down retro-style action/adventure game (pixel art), programming the engine from scratch, using Free Pascal and SDL3.

Thaddy

  • Hero Member
  • *****
  • Posts: 19500
  • Glad to be alive.
Not from me: that is exactly what I asked for and the threadstatic would be a lot less expensive than a threadvar.
Any "programmer" that knows only one programming language is not a programmer

440bx

  • Hero Member
  • *****
  • Posts: 6560
Maybe I'm missing something but...

Aren't all thread vars naturally "threadstatic" anyway ?... the value of a threadvar isn't on the stack, i.e, it doesn't go out of scope when the function that uses it exits.

Am I missing something ?




@Thaddy,

why would a threadstatic be less expensive than a threadvar ?   what is the implementation difference, as you see it, that would make it less expensive ?

I must be missing something...
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19500
  • Glad to be alive.
@440bx
The difference is that - as per my example - a local record declaration works the same.
A threadvar is a heap allocation with a quite complex guard, a threadstatic is a stack allocation and does not need guards: it is either tls or on the thread's stack, which also means there is no clean-up necessary.
You might find the documentation on threadvar interesting:
https://docs.freepascal.org/docs-html/ref/refse26.html

What I propose is just that: make a local var that is static, which currently needs a record.
That is already quite an old technique but seldom used correctly.
« Last Edit: June 06, 2026, 06:22:25 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12959
  • FPC developer.
Admin notice: I've merged the "atomic" thread into this one, and I hope it went well. Please keep the FPC/unleashed topics in the one thread.

Fibonacci

  • Hero Member
  • *****
  • Posts: 1046
  • Behold, I bring salvation - FPC Unleashed
Admin notice: I've merged the "atomic" thread into this one, and I hope it went well. Please keep the FPC/unleashed topics in the one thread.

Just delete it. Duplicate.

Deleting just any posts in this board is not allowed.
FPC Unleashed: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

creaothceann

  • Sr. Member
  • ****
  • Posts: 394
Please keep the FPC/unleashed topics in the one thread.

Perhaps it could be moved into its own subforum, similar to what was done with AI topics?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12959
  • FPC developer.
Admin notice: I've merged the "atomic" thread into this one, and I hope it went well. Please keep the FPC/unleashed topics in the one thread.

Just delete it. Duplicate.

I can't make the distinction any more now that it is merged. However if all relevant contributors empty their post, I'll delete the empty posts.

 

TinyPortal © 2005-2018