Thread-safe way to increment and return an integer in Delphi
Asked Answered
W

3

16

In a single-threaded application I use code like this:

Interface
    function GetNextUID : integer;
Implementation
    function GetNextUID : integer;
    const
      cUID : integer = 0;
    begin
      inc( cUID );
      result := cUID;
    end;

This could of course be implemented as a singleton object, etc. - I'm just giving the simplest possible example.

Q: How can I modify this function (or design a class) to achieve the same result safely from concurrent threads?

Whit answered 25/10, 2010 at 16:52 Comment(1)
Thanks for the quick answers, everyone. I had somehow managed to convince myself that interlockedincrement was incrementing the value in place without returning it - not that it would make any sense that way, but I got stuck on that all the same. Thanks again.Damiandamiani
W
40

You can use the Interlocked* functions:

    function GetNextUID : integer;
    {$J+} // Writeble constants
    const
      cUID : integer = 0;
    begin
      Result := InterlockedIncrement(cUID);
    end;

More modern Delphi versions have renamed these methods into Atomic* (like AtomicDecrement, AtomicIncrement, etc), so the example code becomes this:

    function GetNextUID : integer;
    {$J+} // Writeble constants
    const
      cUID : integer = 0;
    begin
      Result := AtomicIncrement(cUID);
    end;
Wolfgram answered 25/10, 2010 at 16:56 Comment(3)
and +1 for explicitly stating {$J+}. Although I would prefer to make GetNextUID a class function and use a class var for FUID, just because I dislike abusing constants.Tremulous
note: interlocked functions not available in FireMonkey (there should be a cross platform way to increment/decrement?)Pachisi
@AnotherProg they replaced the prefix (see edit), now you can change AtomicIncrement and similar.Reiche
S
16

The easiest way would probably be to just call InterlockedIncrement to do the job.

Slowwitted answered 25/10, 2010 at 16:55 Comment(1)
but note: not available in FireMonkey. Cross Platform way to increment/decrement?Pachisi
K
5

With modern Delphi compilers it is better to use Increment function of class TInterlocked from unit System.SyncObjs. Something like this:

  type
    TMyClass = class
    class var
      FIdCounter: int64;
    var
      FId: int64;
    constructor Create;
    end;

constructor TMyClass.Create;
begin
  FId := TInterlocked.Increment(FIdCounter);
end;

This helps to keep the code platform-independent.

Kutchins answered 27/9, 2015 at 11:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.