Browse Source

* Add TInterlocked by Do-Wan Kim

Michaël Van Canneyt 2 years ago
parent
commit
7aa54010ea
1 changed files with 219 additions and 0 deletions
  1. 219 0
      packages/fcl-base/src/syncobjs.pp

+ 219 - 0
packages/fcl-base/src/syncobjs.pp

@@ -94,6 +94,46 @@ type
    TSimpleEvent = class(TEventObject)
       constructor Create;
    end;
+   
+{$IFDEF CPU16}   
+{$DEFINE NOPOINTER}
+{$ENDIF}
+
+  TInterlocked = class sealed
+    class function Add(var Target: Longint; aIncrement: Longint): Longint; overload; static; inline;
+    class function Exchange(var Target: Longint; Value: Longint): Longint; overload; static; inline;
+    class function CompareExchange(var Target: Longint; Value: Longint; Comparand: Longint): Longint; overload; static; inline;
+    class function CompareExchange(var Target: Longint; Value: Longint; Comparand: Longint; out Succeeded: Boolean): Longint; overload; static;
+    class function Decrement(var Target: Longint): Longint; overload; static; inline;
+    class function Increment(var Target: Longint): Longint; overload; static; inline;
+{$ifdef FPC_HAS_TYPE_SINGLE}
+    class function Exchange(var Target: Single; Value: Single): Single; overload; static; inline;
+    class function CompareExchange(var Target: Single; Value: Single; Comparand: Single): Single; overload; static; inline;
+{$endif}
+{$ifdef cpu64}
+    class function Add(var Target: Int64; aIncrement: Int64): Int64; overload; static; inline;
+    class function Exchange(var Target: Int64; Value: Int64): Int64; overload; static; inline;
+    class function CompareExchange(var Target: Int64; Value: Int64; Comparand: Int64): Int64; overload; static; inline;
+    class function Decrement(var Target: Int64): Int64; overload; static; inline;
+    class function Increment(var Target: Int64): Int64; overload; static; inline;
+    class function Read(var Target: Int64): Int64; static; inline;
+{$ifdef FPC_HAS_TYPE_DOUBLE}
+    class function CompareExchange(var Target: Double; Value: Double; Comparand: Double): Double; overload; static; inline;
+    class function Exchange(var Target: Double; Value: Double): Double; overload; static; inline;
+{$endif}
+{$endif cpu64}
+
+{$IFNDEF NOPOINTER}
+    class function Exchange(var Target: Pointer; Value: Pointer): Pointer; overload; static; inline;
+    class function Exchange(var Target: TObject; Value: TObject): TObject; overload; static; inline;
+    class function CompareExchange(var Target: Pointer; Value: Pointer; Comparand: Pointer): Pointer; overload; static; inline;
+    class function CompareExchange(var Target: TObject; Value: TObject; Comparand: TObject): TObject; overload; static; inline;
+{$ifndef VER3_0}
+    generic class function Exchange<T: class>(var Target: T; Value: T): T; overload; static; inline;
+    generic class function CompareExchange<T: class>(var Target: T; Value: T; Comparand: T): T; overload; static; inline;
+{$endif VER3_0}
+{$ENDIF NOPOINTER}
+  end;
 
 implementation
 
@@ -309,4 +349,183 @@ begin
   inherited Create(nil, True, False, '');
 end;
 
+{ ---------------------------------------------------------------------
+  TInterlocked
+  ---------------------------------------------------------------------}
+
+
+class function TInterlocked.Add(var Target: Longint; aIncrement: Longint): Longint; overload; static; inline;
+var
+  PreviousValue: Longint;
+begin
+  PreviousValue := InterLockedExchangeAdd(Target, aIncrement); // returns previous value
+  Result := PreviousValue + aIncrement;
+end;
+
+
+class function TInterlocked.CompareExchange(var Target: Longint; Value: Longint; Comparand: Longint): Longint; overload; static; inline;
+begin
+  Result := InterlockedCompareExchange(Target, Value, Comparand);
+end;
+
+class function TInterlocked.CompareExchange(var Target: Longint; Value: Longint; Comparand: Longint; out Succeeded: Boolean): Longint; overload; static;
+begin
+  Result := InterlockedCompareExchange(Target, Value, Comparand);
+  Succeeded := (Result = Comparand);
+end;
+
+
+
+class function TInterlocked.Decrement(var Target: Longint): Longint; overload; static; inline;
+begin
+  Result := InterLockedDecrement(Target); // returns new value
+end;
+
+
+class function TInterlocked.Exchange(var Target: Longint; Value: Longint): Longint; overload; static; inline;
+begin
+  Result := InterLockedExchange(Target, Value);
+end;
+
+
+
+
+class function TInterlocked.Increment(var Target: Longint): Longint; overload; static; inline;
+begin
+  Result := InterLockedIncrement(Target); // returns new value
+end;
+
+{ ---------------------------------------------------------------------
+  32-bit single versions
+  ---------------------------------------------------------------------}
+
+{$ifdef FPC_HAS_TYPE_SINGLE}
+class function TInterlocked.Exchange(var Target: Single; Value: Single): Single; overload; static; inline;
+var
+  IntValue: Longint;
+  SinglePtr: PSingle;
+begin
+  IntValue := TInterlocked.Exchange(Longint(Target), Longint(Value));
+  SinglePtr := @IntValue;
+  Result := SinglePtr^;
+end;
+
+class function TInterlocked.CompareExchange(var Target: Single; Value: Single; Comparand: Single): Single; overload; static; inline;
+var
+  IntValue: Longint;
+  SinglePtr: PSingle;
+begin
+  IntValue := TInterlocked.CompareExchange(Longint(Target), Longint(Value), Longint(Comparand));
+  SinglePtr := @IntValue;
+  Result := SinglePtr^;
+end;
+{$endif}
+
+
+{ ---------------------------------------------------------------------
+  64-bit versions
+  ---------------------------------------------------------------------}
+
+{$ifdef cpu64}
+class function TInterlocked.Read(var Target: Int64): Int64; static; inline;
+begin
+  Result := InterlockedCompareExchange64(Target, 0, 0);
+end;
+
+class function TInterlocked.Increment(var Target: Int64): Int64; overload; static; inline;
+begin
+  Result := InterLockedIncrement64(Target); // returns new value
+end;
+
+class function TInterlocked.Exchange(var Target: Int64; Value: Int64): Int64; overload; static; inline;
+begin
+  Result := System.InterLockedExchange64(Target, Value);
+end;
+
+class function TInterlocked.Decrement(var Target: Int64): Int64; overload; static; inline;
+begin
+  Result := InterLockedDecrement64(Target); // returns new value
+end;class function TInterlocked.Add(var Target: Int64; aIncrement: Int64): Int64; overload; static; inline;
+var
+  PreviousValue: Int64;
+begin
+  PreviousValue := System.InterLockedExchangeAdd64(Target, aIncrement); // returns previous value
+  Result := PreviousValue + aIncrement;
+end;
+
+class function TInterlocked.CompareExchange(var Target: Int64; Value: Int64; Comparand: Int64): Int64; overload; static; inline;
+begin
+  Result := System.InterlockedCompareExchange64(Target, Value, Comparand);
+end;
+
+
+{ ---------------------------------------------------------------------
+  64-bit double versions
+  ---------------------------------------------------------------------}
+
+{$ifdef FPC_HAS_TYPE_DOUBLE}
+class function TInterlocked.CompareExchange(var Target: Double; Value: Double; Comparand: Double): Double; overload; static; inline;
+var
+  Int64Value: Int64;
+  DoublePtr: PDouble;
+begin
+  Int64Value := TInterlocked.CompareExchange(Int64(Target), Int64(Value), Int64(Comparand));
+  DoublePtr := @Int64Value;
+  Result := DoublePtr^;
+end;
+{$endif}
+
+{$ifdef FPC_HAS_TYPE_DOUBLE}
+class function TInterlocked.Exchange(var Target: Double; Value: Double): Double; overload; static; inline;
+var
+  Int64Value: Int64;
+  DoublePtr: PDouble;
+begin
+  Int64Value := TInterlocked.Exchange(Int64(Target), Int64(Value));
+  DoublePtr := @Int64Value;
+  Result := DoublePtr^;
+end;
+{$endif}
+
+{$endif cpu64}
+
+{ ---------------------------------------------------------------------
+  Pointer versions
+  ---------------------------------------------------------------------}
+  
+{$IFNDEF NOPOINTER}
+class function TInterlocked.CompareExchange(var Target: Pointer; Value: Pointer; Comparand: Pointer): Pointer; overload; static; inline;
+begin
+  Result := InterlockedCompareExchange(Target, Value, Comparand);
+end;
+
+class function TInterlocked.CompareExchange(var Target: TObject; Value: TObject; Comparand: TObject): TObject; overload; static; inline;
+begin
+  Result := TObject(InterlockedCompareExchange(Pointer(Target), Pointer(Value), Pointer(Comparand)));
+end;
+
+class function TInterlocked.Exchange(var Target: Pointer; Value: Pointer): Pointer; overload; static; inline;
+begin
+  Result := InterLockedExchange(Target, Value);
+end;
+
+class function TInterlocked.Exchange(var Target: TObject; Value: TObject): TObject; overload; static; inline;
+begin
+  Result := TObject(InterLockedExchange(Pointer(Target), Pointer(Value)));
+end;
+
+{$ifndef VER3_0}
+generic class function TInterlocked.CompareExchange<T>(var Target: T; Value: T; Comparand: T): T; overload; static; inline;
+begin
+  Result := T(InterlockedCompareExchange(Pointer(Target), Pointer(Value), Pointer(Comparand)));
+end;
+
+generic class function TInterlocked.Exchange<T>(var Target: T; Value: T): T; overload; static; inline;
+begin
+  Result := T(InterLockedExchange(Pointer(Target), Pointer(Value)));
+end;
+{$endif VER3_0}
+
+{$ENDIF NOPOINTER}
+
 end.