| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- Rev 1.10 2004.10.29 8:49:00 PM czhower
- Fixed a constructor.
- Rev 1.9 2004.10.27 9:20:04 AM czhower
- For TIdStrings
- Rev 1.8 10/26/2004 8:43:02 PM JPMugaas
- Should be more portable with new references to TIdStrings and TIdStringList.
- Rev 1.7 4/12/2004 4:50:36 PM JPMugaas
- TIdThreadSafeInt64 created for some internal work but I figured it would help
- with other stuff.
- Rev 1.6 3/26/2004 1:09:28 PM JPMugaas
- New ThreadSafe objects that I needed for some other work I'm doing.
- Rev 1.5 3/17/2004 8:57:32 PM JPMugaas
- Increment and decrement overloads added for quick math in the
- TIdThreadSafeCardinal and TIdThreadSafeInteger. I need this for personal
- work.
- Rev 1.4 2004.02.25 8:23:20 AM czhower
- Small changes
- Rev 1.3 2004.02.03 4:17:00 PM czhower
- For unit name changes.
- Rev 1.2 2004.01.22 5:59:12 PM czhower
- IdCriticalSection
- Rev 1.1 3/27/2003 12:29:46 AM BGooijen
- Added TIdThreadSafeList.Assign
- Rev 1.0 11/13/2002 09:01:54 AM JPMugaas
- }
- unit IdThreadSafe;
- interface
- {$I IdCompilerDefines.inc}
- //we need to put this in Delphi mode to work
- uses
- Classes,
- {$IFDEF HAS_UNIT_Generics_Collections}
- System.Generics.Collections,
- {$ENDIF}
- IdGlobal;
- type
- TIdThreadSafe = class
- protected
- FCriticalSection: TIdCriticalSection;
- public
- constructor Create; virtual;
- destructor Destroy; override;
- procedure Lock;
- procedure Unlock;
- end;
- // Yes we know that integer operations are "atomic". However we do not like to rely on
- // internal compiler implementation. This is a safe and proper way to keep our code independent
- TIdThreadSafeInteger = class(TIdThreadSafe)
- protected
- FValue: Integer;
- //
- function GetValue: Integer;
- procedure SetValue(const AValue: Integer);
- public
- function Decrement: Integer; overload;
- function Decrement(const AValue : Integer) : Integer; overload;
- function Increment: Integer; overload;
- function Increment(const AValue : Integer) : Integer; overload;
- //
- property Value: Integer read GetValue write SetValue;
- end;
- TIdThreadSafeInt32 = TIdThreadSafeInteger;
- TIdThreadSafeBoolean = class(TIdThreadSafe)
- protected
- FValue: Boolean;
- //
- function GetValue: Boolean;
- procedure SetValue(const AValue: Boolean);
- public
- function Toggle: Boolean;
- //
- property Value: Boolean read GetValue write SetValue;
- end;
- TIdThreadSafeCardinal = class(TIdThreadSafe)
- protected
- FValue: Cardinal;
- //
- function GetValue: Cardinal;
- procedure SetValue(const AValue: Cardinal);
- public
- function Decrement: Cardinal; overload;
- function Decrement(const AValue : Cardinal) : Cardinal; overload;
- function Increment: Cardinal; overload;
- function Increment(const AValue : Cardinal) : Cardinal; overload;
- //
- property Value: Cardinal read GetValue write SetValue;
- end;
- TIdThreadSafeUInt32 = TIdThreadSafeCardinal;
- TIdThreadSafeInt64 = class(TIdThreadSafe)
- protected
- FValue: Int64;
- //
- function GetValue: Int64;
- procedure SetValue(const AValue: Int64);
- public
- function Decrement: Int64; overload;
- function Decrement(const AValue : Int64) : Int64; overload;
- function Increment: Int64; overload;
- function Increment(const AValue : Int64) : Int64; overload;
- //
- property Value: Int64 read GetValue write SetValue;
- end;
- TIdThreadSafeString = class(TIdThreadSafe)
- protected
- FValue: string;
- //
- function GetValue: string;
- procedure SetValue(const AValue: string);
- public
- procedure Append(const AValue: string);
- procedure Prepend(const AValue: string);
- //
- property Value: string read GetValue write SetValue;
- end;
- TIdThreadSafeStringList = class(TIdThreadSafe)
- protected
- FValue: TStringList;
- //
- function GetValue(const AName: string): string;
- procedure SetValue(const AName, AValue: string);
- public
- constructor Create; override;
- destructor Destroy; override;
- procedure Add(const AItem: string);
- procedure AddObject(const AItem: string; AObject: TObject);
- procedure Clear;
- function Empty: Boolean;
- function Lock: TStringList; reintroduce;
- function ObjectByItem(const AItem: string): TObject;
- procedure Remove(const AItem: string);
- procedure Unlock; reintroduce;
- property Values[const AName: string]: string read GetValue write SetValue;
- end;
- TIdThreadSafeDateTime = class(TIdThreadSafe)
- protected
- FValue : TDateTime;
- function GetValue: TDateTime;
- procedure SetValue(const AValue: TDateTime);
- public
- procedure Add(const AValue : TDateTime);
- procedure Subtract(const AValue : TDateTime);
- property Value: TDateTime read GetValue write SetValue;
- end;
- //In D7, a double is the same as a TDateTime. In DotNET, it is not.
- TIdThreadSafeDouble = class(TIdThreadSafe)
- protected
- FValue : Double;
- function GetValue: Double;
- procedure SetValue(const AValue: Double);
- public
- procedure Add(const AValue : Double);
- procedure Subtract(const AValue : Double);
- property Value: Double read GetValue write SetValue;
- end;
- //TODO: Later make this descend from TIdThreadSafe instead
- {$IFDEF HAS_GENERICS_TThreadList}
- TIdThreadSafeList<T> = class(TThreadList<T>)
- {$ELSE}
- TIdThreadSafeList = class(TThreadList)
- {$ENDIF}
- public
- procedure Assign(AThreadList: TThreadList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF});overload;
- procedure Assign(AList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF});overload;
- // Here to make it virtual
- constructor Create; virtual;
- function IsCountLessThan(const AValue: UInt32): Boolean;
- function Count:Integer;
- function IsEmpty: Boolean;
- function Pop: {$IFDEF HAS_GENERICS_TThreadList}T{$ELSE}Pointer{$ENDIF};
- function Pull: {$IFDEF HAS_GENERICS_TThreadList}T{$ELSE}Pointer{$ENDIF};
- end;
- {$IFDEF HAS_GENERICS_TObjectList}
- TIdThreadSafeObjectList<T: class> = class(TIdThreadSafeList<T>)
- {$ELSE}
- TIdThreadSafeObjectList = class(TIdThreadSafeList)
- {$ENDIF}
- {$IFNDEF USE_OBJECT_ARC}
- private
- FOwnsObjects: Boolean;
- {$ENDIF}
- public
- {$IFNDEF USE_OBJECT_ARC}
- constructor Create; override;
- destructor Destroy; override;
- {$ENDIF}
- procedure ClearAndFree;
- {$IFNDEF USE_OBJECT_ARC}
- property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
- {$ENDIF}
- end;
- implementation
- uses
- {$IFDEF VCL_2010_OR_ABOVE}
- {$IFDEF WINDOWS}
- Windows,
- {$ENDIF}
- {$ENDIF}
- {$IFDEF VCL_XE3_OR_ABOVE}
- System.SyncObjs,
- {$ENDIF}
- SysUtils;
- { TIdThreadSafe }
- constructor TIdThreadSafe.Create;
- begin
- inherited Create;
- FCriticalSection := TIdCriticalSection.Create;
- end;
- destructor TIdThreadSafe.Destroy;
- begin
- FreeAndNil(FCriticalSection);
- inherited Destroy;
- end;
- procedure TIdThreadSafe.Lock;
- begin
- FCriticalSection.Enter;
- end;
- procedure TIdThreadSafe.Unlock;
- begin
- FCriticalSection.Leave;
- end;
- { TIdThreadSafeInteger }
- function TIdThreadSafeInteger.Decrement: Integer;
- begin
- Lock;
- try
- Result := FValue;
- Dec(FValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInteger.Decrement(const AValue: Integer): Integer;
- begin
- Lock;
- try
- Result := FValue;
- Dec(FValue,AValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInteger.GetValue: Integer;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInteger.Increment: Integer;
- begin
- Lock;
- try
- Result := FValue;
- Inc(FValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInteger.Increment(const AValue: Integer): Integer;
- begin
- Lock;
- try
- Result := FValue;
- Inc(FValue,AValue);
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeInteger.SetValue(const AValue: Integer);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- { TIdThreadSafeString }
- procedure TIdThreadSafeString.Append(const AValue: string);
- begin
- Lock;
- try
- FValue := FValue + AValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeString.GetValue: string;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeString.Prepend(const AValue: string);
- begin
- Lock;
- try
- FValue := AValue + FValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeString.SetValue(const AValue: string);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- { TIdThreadSafeStringList }
- procedure TIdThreadSafeStringList.Add(const AItem: string);
- begin
- Lock;
- try
- FValue.Add(AItem);
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeStringList.AddObject(const AItem: string; AObject: TObject);
- begin
- Lock;
- try
- FValue.AddObject(AItem, AObject);
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeStringList.Clear;
- begin
- Lock;
- try
- FValue.Clear;
- finally
- Unlock;
- end;
- end;
- constructor TIdThreadSafeStringList.Create;
- begin
- inherited Create;
- FValue := TStringList.Create;
- end;
- destructor TIdThreadSafeStringList.Destroy;
- begin
- inherited Lock;
- try
- FreeAndNil(FValue);
- finally
- inherited Unlock;
- end;
- inherited Destroy;
- end;
- function TIdThreadSafeStringList.Empty: Boolean;
- begin
- Lock;
- try
- Result := FValue.Count = 0;
- finally Unlock; end;
- end;
- function TIdThreadSafeStringList.GetValue(const AName: string): string;
- begin
- Lock;
- try
- Result := FValue.Values[AName];
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeStringList.Lock: TStringList;
- begin
- inherited Lock;
- Result := FValue;
- end;
- function TIdThreadSafeStringList.ObjectByItem(const AItem: string): TObject;
- var
- i: Integer;
- begin
- Result := nil;
- Lock;
- try
- i := FValue.IndexOf(AItem);
- if i > -1 then begin
- Result := FValue.Objects[i];
- end;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeStringList.Remove(const AItem: string);
- var
- i: Integer;
- begin
- Lock;
- try
- i := FValue.IndexOf(AItem);
- if i > -1 then begin
- FValue.Delete(i);
- end;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeStringList.SetValue(const AName, AValue: string);
- begin
- Lock;
- try
- FValue.Values[AName] := AValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeStringList.Unlock;
- begin
- inherited Unlock;
- end;
- { TIdThreadSafeCardinal }
- function TIdThreadSafeCardinal.Decrement: Cardinal;
- begin
- Lock;
- try
- Result := FValue;
- Dec(FValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeCardinal.Decrement(const AValue: Cardinal): Cardinal;
- begin
- Lock;
- try
- Result := FValue;
- Dec(FValue,AValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeCardinal.GetValue: Cardinal;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeCardinal.Increment: Cardinal;
- begin
- Lock;
- try
- Result := FValue;
- Inc(FValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeCardinal.Increment(const AValue: Cardinal): Cardinal;
- begin
- Lock;
- try
- Result := FValue;
- Inc(FValue,AValue);
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeCardinal.SetValue(const AValue: Cardinal);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- { TIdThreadSafeList }
- function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.IsCountLessThan(const AValue: UInt32): Boolean;
- begin
- if Assigned(Self) then begin
- Result := UInt32(Count) < AValue;
- end else begin
- Result := True; // none always <
- end;
- end;
- function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.IsEmpty: Boolean;
- begin
- Result := IsCountLessThan(1);
- end;
- {$IFDEF HAS_GENERICS_TThreadList}
- function TIdThreadSafeList<T>.Pop: T;
- {$ELSE}
- function TIdThreadSafeList.Pop: Pointer;
- {$ENDIF}
- var
- LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
- begin
- LList := LockList;
- try
- if LList.Count > 0 then begin
- Result := LList.Items[Count - 1];
- LList.Delete(Count - 1);
- end else begin
- Result := {$IFDEF HAS_GENERICS_TThreadList}Default(T){$ELSE}nil{$ENDIF};
- end;
- finally
- UnlockList;
- end;
- end;
- {$IFDEF HAS_GENERICS_TThreadList}
- function TIdThreadSafeList<T>.Pull: T;
- {$ELSE}
- function TIdThreadSafeList.Pull: Pointer;
- {$ENDIF}
- var
- LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
- begin
- LList := LockList;
- try
- if LList.Count > 0 then begin
- Result := LList.Items[0];
- LList.Delete(0);
- end else begin
- Result := {$IFDEF HAS_GENERICS_TThreadList}Default(T){$ELSE}nil{$ENDIF};
- end;
- finally
- UnlockList;
- end;
- end;
- {$IFDEF HAS_GENERICS_TThreadList}
- procedure TIdThreadSafeList<T>.Assign(AList: TList<T>);
- {$ELSE}
- procedure TIdThreadSafeList.Assign(AList: TList);
- {$ENDIF}
- var
- i: integer;
- LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
- begin
- LList := LockList;
- try
- LList.Clear;
- LList.Capacity := AList.Capacity;
- for i := 0 to AList.Count - 1 do begin
- LList.Add(AList.Items[i]);
- end;
- finally
- UnlockList;
- end;
- end;
- {$IFDEF HAS_GENERICS_TThreadList}
- procedure TIdThreadSafeList<T>.Assign(AThreadList: TThreadList<T>);
- {$ELSE}
- procedure TIdThreadSafeList.Assign(AThreadList: TThreadList);
- {$ENDIF}
- var
- LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
- begin
- LList := AThreadList.LockList;
- try
- Assign(LList);
- finally
- AThreadList.UnlockList;
- end;
- end;
- constructor TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.Create;
- begin
- inherited Create;
- end;
- function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.Count: Integer;
- var
- LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
- begin
- LList := LockList;
- try
- Result := LList.Count;
- finally
- UnlockList;
- end;
- end;
- { TIdThreadSafeObjectList }
- {$IFNDEF USE_OBJECT_ARC}
- constructor TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.Create;
- begin
- inherited Create;
- OwnsObjects := False;
- end;
- destructor TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.Destroy;
- begin
- if OwnsObjects then ClearAndFree;
- inherited;
- end;
- {$ENDIF}
- procedure TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.ClearAndFree;
- var
- LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
- i: Integer;
- begin
- LList := LockList;
- try
- {$IFNDEF USE_OBJECT_ARC}
- for i := 0 to LList.Count-1 do begin
- {$IFDEF HAS_GENERICS_TList}LList[i]{$ELSE}TObject(LList[i]){$ENDIF}.Free;
- end;
- {$ENDIF}
- LList.Clear;
- finally
- UnlockList;
- end;
- end;
- { TIdThreadSafeBoolean }
- function TIdThreadSafeBoolean.GetValue: Boolean;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeBoolean.SetValue(const AValue: Boolean);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeBoolean.Toggle: Boolean;
- begin
- Lock;
- try
- FValue := not FValue;
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- { TIdThreadSafeDateTime }
- procedure TIdThreadSafeDateTime.Add(const AValue: TDateTime);
- begin
- Lock;
- try
- FValue := FValue + AValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeDateTime.GetValue: TDateTime;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeDateTime.SetValue(const AValue: TDateTime);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeDateTime.Subtract(const AValue: TDateTime);
- begin
- Lock;
- try
- FValue := FValue - AValue;
- finally
- Unlock;
- end;
- end;
- { TIdThreadSafeDouble }
- procedure TIdThreadSafeDouble.Add(const AValue: Double);
- begin
- Lock;
- try
- FValue := FValue + AValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeDouble.GetValue: Double;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeDouble.SetValue(const AValue: Double);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeDouble.Subtract(const AValue: Double);
- begin
- Lock;
- try
- FValue := FValue - AValue;
- finally
- Unlock;
- end;
- end;
- { TIdThreadSafeInt64 }
- function TIdThreadSafeInt64.Decrement(const AValue: Int64): Int64;
- begin
- Lock;
- try
- Result := FValue;
- Dec(FValue,AValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInt64.Decrement: Int64;
- begin
- Lock;
- try
- Result := FValue;
- Dec(FValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInt64.GetValue: Int64;
- begin
- Lock;
- try
- Result := FValue;
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInt64.Increment(const AValue: Int64): Int64;
- begin
- Lock;
- try
- Result := FValue;
- Inc(FValue,AValue);
- finally
- Unlock;
- end;
- end;
- function TIdThreadSafeInt64.Increment: Int64;
- begin
- Lock;
- try
- Result := FValue;
- Inc(FValue);
- finally
- Unlock;
- end;
- end;
- procedure TIdThreadSafeInt64.SetValue(const AValue: Int64);
- begin
- Lock;
- try
- FValue := AValue;
- finally
- Unlock;
- end;
- end;
- end.
|