2010-10-25 18 views
14

Dans une application mono-thread j'utiliser le code comme ceci:façon fil de sécurité pour incrémenter et retourner un entier Delphi

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

Cela pourrait bien entendu être mis en œuvre comme un objet singleton, etc. - je Je donne juste l'exemple le plus simple possible.

Q: Comment puis-je modifier cette fonction (ou concevoir une classe) pour obtenir le même résultat en toute sécurité à partir de threads concurrents?

+0

Merci pour les réponses rapides, tout le monde. J'avais en quelque sorte réussi à me convaincre que l'incrustation incrustée augmentait la valeur en place sans la retourner - pas que ça aurait un sens, mais je me suis quand même coincé là-dessus. Merci encore. –

Répondre

35

Vous pouvez utiliser les Interlocked* fonctions:

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

plus modernes versions Delphi ont rebaptisé ces méthodes en Atomic* (comme AtomicDecrement, AtomicIncrement, etc.), de sorte que le code exemple devient ceci:

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

+1 pour donner aussi l'exemple. –

+5

et +1 pour indiquer explicitement {$ J +}. Bien que je préférerais faire GetNextUID une fonction de classe et utiliser une classe var pour FUID, juste parce que je n'aime pas abuser des constantes. –

+0

note: les fonctions interverrouillées ne sont pas disponibles dans FireMonkey (il devrait y avoir une façon multi-plateforme d'incrémenter/décrémenter?) –

15

Le moyen le plus simple serait probablement d'appeler simplement InterlockedIncrement pour faire le travail.

+0

mais notez: non disponible dans FireMonkey. Cross Platform façon d'incrémenter/décrémenter? –

4

Avec les compilateurs Delphi modernes, il est préférable d'utiliser la fonction Increment de la classe TInterlocked de l'unité System.SyncObjs. Quelque chose comme ceci:

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

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

Cela permet de garder le code indépendant de la plate-forme.