2017-04-22 10 views
11

Delphi 10.2 (prenant en charge Linux) a une fonction multiplateforme AtomicExchange qui est équivalente à Windows InterlocekdEchange. Jusqu'ici tout va bien ...Equivalent de InterlockedExchangeAdd pour Linux en utilisant Delphi 10.2)

Je dois porter le code Win32 en utilisant InterlockedExchangeAdd qui n'a pas d'équivalent AtomicExchangeAdd.

Ma question est: que puis-je utiliser pour remplacer InterlockedExchangeAdd lors de la compilation pour Linux?

+0

http://stackoverflow.com/q/2287451/505088 –

Répondre

10

InterlockedExchangeAdd() « effectue une addition atomique de Valeur à la valeur pointée par Cumulande. Le résultat est stocké dans l'adresse spécifiée par Cumulande. »

L'unité System.SyncObjs a une classe TInterlocked, qui a surchargé Add() méthodes pour faire la même chose:

incrémente un nombre entier avec une autre. Il existe deux méthodes Add surchargées. Les deux méthodes Add incrémentent un Target par Increment.

class function Add(var Target: Integer; Increment: Integer): Integer; overload; static; inline; 

class function Add(var Target: Int64; Increment: Int64): Int64; overload; static; inline; 

La différence est que InterlockedExchangeAdd() « retourne la valeur initiale de la variable pointée par Cumulande », alors que TInterlocked.Add() « retourne la valeur du paramètre incrémenté » à la place. Donc, si vous utilisez la valeur de retour, vous devrez tenir compte de cette différence, par exemple:

function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer; 
begin 
    Result := TInterlocked.Add(Addend, Value) - Value; 
end; 
+0

Est-ce vraiment emboîtés (atomique)? En passant, TInterlocked est juste un wrapper autour de la fonction AtomicXYZ. – fpiette

+0

@fpiette oui, c'est un wrapper, mais c'est aussi une interface publique multiplateforme pour les opérations atomiques. –

+1

'AtomicIncrement' etc. sont également multiplate-forme publique. Vous pouvez choisir soit. –

11

Il y a une mise en œuvre cachée de cette fonction dans System.SysUtils.pas:

function AtomicExchangeAdd(var Addend: Integer; Value: Integer): Integer; 
begin 
    Result := AtomicIncrement(Addend, Value) - Value; 
end; 

Il utilise le fait que AtomicIncrement retourne la nouvelle valeur de Cumulande, tandis que InterlockedExchangeAdd renvoie l'ancienne valeur. Soustraire La valeur donne le résultat attendu et est évidemment thread-safe.