IdThreadSafe.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.10 2004.10.29 8:49:00 PM czhower
  18. Fixed a constructor.
  19. Rev 1.9 2004.10.27 9:20:04 AM czhower
  20. For TIdStrings
  21. Rev 1.8 10/26/2004 8:43:02 PM JPMugaas
  22. Should be more portable with new references to TIdStrings and TIdStringList.
  23. Rev 1.7 4/12/2004 4:50:36 PM JPMugaas
  24. TIdThreadSafeInt64 created for some internal work but I figured it would help
  25. with other stuff.
  26. Rev 1.6 3/26/2004 1:09:28 PM JPMugaas
  27. New ThreadSafe objects that I needed for some other work I'm doing.
  28. Rev 1.5 3/17/2004 8:57:32 PM JPMugaas
  29. Increment and decrement overloads added for quick math in the
  30. TIdThreadSafeCardinal and TIdThreadSafeInteger. I need this for personal
  31. work.
  32. Rev 1.4 2004.02.25 8:23:20 AM czhower
  33. Small changes
  34. Rev 1.3 2004.02.03 4:17:00 PM czhower
  35. For unit name changes.
  36. Rev 1.2 2004.01.22 5:59:12 PM czhower
  37. IdCriticalSection
  38. Rev 1.1 3/27/2003 12:29:46 AM BGooijen
  39. Added TIdThreadSafeList.Assign
  40. Rev 1.0 11/13/2002 09:01:54 AM JPMugaas
  41. }
  42. unit IdThreadSafe;
  43. interface
  44. {$I IdCompilerDefines.inc}
  45. //we need to put this in Delphi mode to work
  46. uses
  47. Classes,
  48. {$IFDEF HAS_UNIT_Generics_Collections}
  49. System.Generics.Collections,
  50. {$ENDIF}
  51. IdGlobal;
  52. type
  53. TIdThreadSafe = class
  54. protected
  55. FCriticalSection: TIdCriticalSection;
  56. public
  57. constructor Create; virtual;
  58. destructor Destroy; override;
  59. procedure Lock;
  60. procedure Unlock;
  61. end;
  62. // Yes we know that integer operations are "atomic". However we do not like to rely on
  63. // internal compiler implementation. This is a safe and proper way to keep our code independent
  64. TIdThreadSafeInt32 = class(TIdThreadSafe)
  65. protected
  66. FValue: Int32;
  67. //
  68. function GetValue: Int32;
  69. procedure SetValue(const AValue: Int32);
  70. public
  71. function Decrement(const AValue : Int32 = 1) : Int32;
  72. function Increment(const AValue : Int32 = 1) : Int32;
  73. //
  74. property Value: Int32 read GetValue write SetValue;
  75. end;
  76. TIdThreadSafeInteger = TIdThreadSafeInt32 deprecated 'use TIdThreadSafeInt32';
  77. TIdThreadSafeBoolean = class(TIdThreadSafe)
  78. protected
  79. FValue: Boolean;
  80. //
  81. function GetValue: Boolean;
  82. procedure SetValue(const AValue: Boolean);
  83. public
  84. function Toggle: Boolean;
  85. //
  86. property Value: Boolean read GetValue write SetValue;
  87. end;
  88. TIdThreadSafeUInt32 = class(TIdThreadSafe)
  89. protected
  90. FValue: UInt32;
  91. //
  92. function GetValue: UInt32;
  93. procedure SetValue(const AValue: UInt32);
  94. public
  95. function Decrement(const AValue : UInt32 = 1) : UInt32;
  96. function Increment(const AValue : UInt32 = 1) : UInt32;
  97. //
  98. property Value: Cardinal read GetValue write SetValue;
  99. end;
  100. TIdThreadSafeCardinal = TIdThreadSafeUInt32 deprecated 'use TIdThreadSafeUInt32';
  101. TIdThreadSafeInt64 = class(TIdThreadSafe)
  102. protected
  103. FValue: Int64;
  104. //
  105. function GetValue: Int64;
  106. procedure SetValue(const AValue: Int64);
  107. public
  108. function Decrement(const AValue : Int64 = 1) : Int64;
  109. function Increment(const AValue : Int64 = 1) : Int64;
  110. //
  111. property Value: Int64 read GetValue write SetValue;
  112. end;
  113. TIdThreadSafeUInt64 = class(TIdThreadSafe)
  114. protected
  115. FValue: UInt64;
  116. //
  117. function GetValue: UInt64;
  118. procedure SetValue(const AValue: UInt64);
  119. public
  120. function Decrement(const AValue : UInt64 = 1) : UInt64;
  121. function Increment(const AValue : UInt64 = 1) : UInt64;
  122. //
  123. property Value: UInt64 read GetValue write SetValue;
  124. end;
  125. TIdThreadSafeString = class(TIdThreadSafe)
  126. protected
  127. FValue: string;
  128. //
  129. function GetValue: string;
  130. procedure SetValue(const AValue: string);
  131. public
  132. procedure Append(const AValue: string);
  133. procedure Prepend(const AValue: string);
  134. //
  135. property Value: string read GetValue write SetValue;
  136. end;
  137. TIdThreadSafeStringList = class(TIdThreadSafe)
  138. protected
  139. FValue: TStringList;
  140. //
  141. function GetValue(const AName: string): string;
  142. procedure SetValue(const AName, AValue: string);
  143. public
  144. constructor Create; override;
  145. destructor Destroy; override;
  146. procedure Add(const AItem: string);
  147. procedure AddObject(const AItem: string; AObject: TObject);
  148. procedure Clear;
  149. function Empty: Boolean;
  150. function Lock: TStringList; reintroduce;
  151. function ObjectByItem(const AItem: string): TObject;
  152. procedure Remove(const AItem: string);
  153. procedure Unlock; reintroduce;
  154. property Values[const AName: string]: string read GetValue write SetValue;
  155. end;
  156. TIdThreadSafeDateTime = class(TIdThreadSafe)
  157. protected
  158. FValue : TDateTime;
  159. function GetValue: TDateTime;
  160. procedure SetValue(const AValue: TDateTime);
  161. public
  162. procedure Add(const AValue : TDateTime);
  163. procedure Subtract(const AValue : TDateTime);
  164. property Value: TDateTime read GetValue write SetValue;
  165. end;
  166. //In D7, a double is the same as a TDateTime. In DotNET, it is not.
  167. TIdThreadSafeDouble = class(TIdThreadSafe)
  168. protected
  169. FValue : Double;
  170. function GetValue: Double;
  171. procedure SetValue(const AValue: Double);
  172. public
  173. procedure Add(const AValue : Double);
  174. procedure Subtract(const AValue : Double);
  175. property Value: Double read GetValue write SetValue;
  176. end;
  177. //TODO: Later make this descend from TIdThreadSafe instead
  178. {$IFDEF HAS_GENERICS_TThreadList}
  179. TIdThreadSafeList<T> = class(TThreadList<T>)
  180. {$ELSE}
  181. TIdThreadSafeList = class(TThreadList)
  182. {$ENDIF}
  183. public
  184. procedure Assign(AThreadList: TThreadList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF});overload;
  185. procedure Assign(AList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF});overload;
  186. // Here to make it virtual
  187. constructor Create; virtual;
  188. function IsCountLessThan(const AValue: UInt32): Boolean;
  189. function Count:Integer;
  190. function IsEmpty: Boolean;
  191. function Pop: {$IFDEF HAS_GENERICS_TThreadList}T{$ELSE}Pointer{$ENDIF};
  192. function Pull: {$IFDEF HAS_GENERICS_TThreadList}T{$ELSE}Pointer{$ENDIF};
  193. end;
  194. {$IFDEF HAS_GENERICS_TObjectList}
  195. TIdThreadSafeObjectList<T: class> = class(TIdThreadSafeList<T>)
  196. {$ELSE}
  197. TIdThreadSafeObjectList = class(TIdThreadSafeList)
  198. {$ENDIF}
  199. {$IFNDEF USE_OBJECT_ARC}
  200. private
  201. FOwnsObjects: Boolean;
  202. {$ENDIF}
  203. public
  204. {$IFNDEF USE_OBJECT_ARC}
  205. constructor Create; override;
  206. destructor Destroy; override;
  207. {$ENDIF}
  208. procedure ClearAndFree;
  209. {$IFNDEF USE_OBJECT_ARC}
  210. property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
  211. {$ENDIF}
  212. end;
  213. implementation
  214. uses
  215. {$IF DEFINED(WINDOWS) AND DEFINED(DCC_2010_OR_ABOVE)}
  216. Windows,
  217. {$IFEND}
  218. {$IFDEF DCC_XE3_OR_ABOVE}
  219. System.SyncObjs,
  220. {$ENDIF}
  221. SysUtils;
  222. { TIdThreadSafe }
  223. constructor TIdThreadSafe.Create;
  224. begin
  225. inherited Create;
  226. FCriticalSection := TIdCriticalSection.Create;
  227. end;
  228. destructor TIdThreadSafe.Destroy;
  229. begin
  230. FCriticalSection.Free;
  231. inherited Destroy;
  232. end;
  233. procedure TIdThreadSafe.Lock;
  234. begin
  235. FCriticalSection.Enter;
  236. end;
  237. procedure TIdThreadSafe.Unlock;
  238. begin
  239. FCriticalSection.Leave;
  240. end;
  241. { TIdThreadSafeInt32 }
  242. function TIdThreadSafeInt32.Decrement(const AValue: Int32 = 1): Int32;
  243. begin
  244. Lock;
  245. try
  246. Result := FValue;
  247. Dec(FValue, AValue);
  248. finally
  249. Unlock;
  250. end;
  251. end;
  252. function TIdThreadSafeInt32.GetValue: Int32;
  253. begin
  254. Lock;
  255. try
  256. Result := FValue;
  257. finally
  258. Unlock;
  259. end;
  260. end;
  261. function TIdThreadSafeInt32.Increment(const AValue: Int32 = 1): Int32;
  262. begin
  263. Lock;
  264. try
  265. Result := FValue;
  266. Inc(FValue, AValue);
  267. finally
  268. Unlock;
  269. end;
  270. end;
  271. procedure TIdThreadSafeInt32.SetValue(const AValue: Int32);
  272. begin
  273. Lock;
  274. try
  275. FValue := AValue;
  276. finally
  277. Unlock;
  278. end;
  279. end;
  280. { TIdThreadSafeString }
  281. procedure TIdThreadSafeString.Append(const AValue: string);
  282. begin
  283. Lock;
  284. try
  285. FValue := FValue + AValue;
  286. finally
  287. Unlock;
  288. end;
  289. end;
  290. function TIdThreadSafeString.GetValue: string;
  291. begin
  292. Lock;
  293. try
  294. Result := FValue;
  295. finally
  296. Unlock;
  297. end;
  298. end;
  299. procedure TIdThreadSafeString.Prepend(const AValue: string);
  300. begin
  301. Lock;
  302. try
  303. FValue := AValue + FValue;
  304. finally
  305. Unlock;
  306. end;
  307. end;
  308. procedure TIdThreadSafeString.SetValue(const AValue: string);
  309. begin
  310. Lock;
  311. try
  312. FValue := AValue;
  313. finally
  314. Unlock;
  315. end;
  316. end;
  317. { TIdThreadSafeStringList }
  318. procedure TIdThreadSafeStringList.Add(const AItem: string);
  319. begin
  320. Lock;
  321. try
  322. FValue.Add(AItem);
  323. finally
  324. Unlock;
  325. end;
  326. end;
  327. procedure TIdThreadSafeStringList.AddObject(const AItem: string; AObject: TObject);
  328. begin
  329. Lock;
  330. try
  331. FValue.AddObject(AItem, AObject);
  332. finally
  333. Unlock;
  334. end;
  335. end;
  336. procedure TIdThreadSafeStringList.Clear;
  337. begin
  338. Lock;
  339. try
  340. FValue.Clear;
  341. finally
  342. Unlock;
  343. end;
  344. end;
  345. constructor TIdThreadSafeStringList.Create;
  346. begin
  347. inherited Create;
  348. FValue := TStringList.Create;
  349. end;
  350. destructor TIdThreadSafeStringList.Destroy;
  351. begin
  352. inherited Lock;
  353. try
  354. FValue.Free;
  355. finally
  356. inherited Unlock;
  357. end;
  358. inherited Destroy;
  359. end;
  360. function TIdThreadSafeStringList.Empty: Boolean;
  361. begin
  362. Lock;
  363. try
  364. Result := FValue.Count = 0;
  365. finally Unlock; end;
  366. end;
  367. function TIdThreadSafeStringList.GetValue(const AName: string): string;
  368. begin
  369. Lock;
  370. try
  371. Result := FValue.Values[AName];
  372. finally
  373. Unlock;
  374. end;
  375. end;
  376. function TIdThreadSafeStringList.Lock: TStringList;
  377. begin
  378. inherited Lock;
  379. Result := FValue;
  380. end;
  381. function TIdThreadSafeStringList.ObjectByItem(const AItem: string): TObject;
  382. var
  383. i: Integer;
  384. begin
  385. Result := nil;
  386. Lock;
  387. try
  388. i := FValue.IndexOf(AItem);
  389. if i > -1 then begin
  390. Result := FValue.Objects[i];
  391. end;
  392. finally
  393. Unlock;
  394. end;
  395. end;
  396. procedure TIdThreadSafeStringList.Remove(const AItem: string);
  397. var
  398. i: Integer;
  399. begin
  400. Lock;
  401. try
  402. i := FValue.IndexOf(AItem);
  403. if i > -1 then begin
  404. FValue.Delete(i);
  405. end;
  406. finally
  407. Unlock;
  408. end;
  409. end;
  410. procedure TIdThreadSafeStringList.SetValue(const AName, AValue: string);
  411. begin
  412. Lock;
  413. try
  414. FValue.Values[AName] := AValue;
  415. finally
  416. Unlock;
  417. end;
  418. end;
  419. procedure TIdThreadSafeStringList.Unlock;
  420. begin
  421. inherited Unlock;
  422. end;
  423. { TIdThreadSafeUInt32 }
  424. function TIdThreadSafeUInt32.Decrement(const AValue: UInt32 = 1): UInt32;
  425. begin
  426. Lock;
  427. try
  428. Result := FValue;
  429. Dec(FValue, AValue);
  430. finally
  431. Unlock;
  432. end;
  433. end;
  434. function TIdThreadSafeUInt32.GetValue: UInt32;
  435. begin
  436. Lock;
  437. try
  438. Result := FValue;
  439. finally
  440. Unlock;
  441. end;
  442. end;
  443. function TIdThreadSafeUInt32.Increment(const AValue: UInt32 = 1): UInt32;
  444. begin
  445. Lock;
  446. try
  447. Result := FValue;
  448. Inc(FValue, AValue);
  449. finally
  450. Unlock;
  451. end;
  452. end;
  453. procedure TIdThreadSafeUInt32.SetValue(const AValue: UInt32);
  454. begin
  455. Lock;
  456. try
  457. FValue := AValue;
  458. finally
  459. Unlock;
  460. end;
  461. end;
  462. { TIdThreadSafeList }
  463. function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.IsCountLessThan(const AValue: UInt32): Boolean;
  464. begin
  465. if Assigned(Self) then begin
  466. Result := UInt32(Count) < AValue;
  467. end else begin
  468. Result := True; // none always <
  469. end;
  470. end;
  471. function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.IsEmpty: Boolean;
  472. begin
  473. Result := IsCountLessThan(1);
  474. end;
  475. {$IFDEF HAS_GENERICS_TThreadList}
  476. function TIdThreadSafeList<T>.Pop: T;
  477. {$ELSE}
  478. function TIdThreadSafeList.Pop: Pointer;
  479. {$ENDIF}
  480. var
  481. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  482. begin
  483. LList := LockList;
  484. try
  485. if LList.Count > 0 then begin
  486. Result := LList.Items[Count - 1];
  487. LList.Delete(Count - 1);
  488. end else begin
  489. Result := {$IFDEF HAS_GENERICS_TThreadList}Default(T){$ELSE}nil{$ENDIF};
  490. end;
  491. finally
  492. UnlockList;
  493. end;
  494. end;
  495. {$IFDEF HAS_GENERICS_TThreadList}
  496. function TIdThreadSafeList<T>.Pull: T;
  497. {$ELSE}
  498. function TIdThreadSafeList.Pull: Pointer;
  499. {$ENDIF}
  500. var
  501. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  502. begin
  503. LList := LockList;
  504. try
  505. if LList.Count > 0 then begin
  506. Result := LList.Items[0];
  507. LList.Delete(0);
  508. end else begin
  509. Result := {$IFDEF HAS_GENERICS_TThreadList}Default(T){$ELSE}nil{$ENDIF};
  510. end;
  511. finally
  512. UnlockList;
  513. end;
  514. end;
  515. {$IFDEF HAS_GENERICS_TThreadList}
  516. procedure TIdThreadSafeList<T>.Assign(AList: TList<T>);
  517. {$ELSE}
  518. procedure TIdThreadSafeList.Assign(AList: TList);
  519. {$ENDIF}
  520. var
  521. i: integer;
  522. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  523. begin
  524. LList := LockList;
  525. try
  526. LList.Clear;
  527. LList.Capacity := AList.Capacity;
  528. for i := 0 to AList.Count - 1 do begin
  529. LList.Add(AList.Items[i]);
  530. end;
  531. finally
  532. UnlockList;
  533. end;
  534. end;
  535. {$IFDEF HAS_GENERICS_TThreadList}
  536. procedure TIdThreadSafeList<T>.Assign(AThreadList: TThreadList<T>);
  537. {$ELSE}
  538. procedure TIdThreadSafeList.Assign(AThreadList: TThreadList);
  539. {$ENDIF}
  540. var
  541. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  542. begin
  543. LList := AThreadList.LockList;
  544. try
  545. Assign(LList);
  546. finally
  547. AThreadList.UnlockList;
  548. end;
  549. end;
  550. constructor TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.Create;
  551. begin
  552. inherited Create;
  553. end;
  554. function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.Count: Integer;
  555. var
  556. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  557. begin
  558. LList := LockList;
  559. try
  560. Result := LList.Count;
  561. finally
  562. UnlockList;
  563. end;
  564. end;
  565. { TIdThreadSafeObjectList }
  566. {$IFNDEF USE_OBJECT_ARC}
  567. constructor TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.Create;
  568. begin
  569. inherited Create;
  570. OwnsObjects := False;
  571. end;
  572. destructor TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.Destroy;
  573. begin
  574. if OwnsObjects then ClearAndFree;
  575. inherited;
  576. end;
  577. {$ENDIF}
  578. procedure TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.ClearAndFree;
  579. var
  580. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  581. i: Integer;
  582. begin
  583. LList := LockList;
  584. try
  585. {$IFNDEF USE_OBJECT_ARC}
  586. for i := 0 to LList.Count-1 do begin
  587. {$IFDEF HAS_GENERICS_TList}LList[i]{$ELSE}TObject(LList[i]){$ENDIF}.Free;
  588. end;
  589. {$ENDIF}
  590. LList.Clear;
  591. finally
  592. UnlockList;
  593. end;
  594. end;
  595. { TIdThreadSafeBoolean }
  596. function TIdThreadSafeBoolean.GetValue: Boolean;
  597. begin
  598. Lock;
  599. try
  600. Result := FValue;
  601. finally
  602. Unlock;
  603. end;
  604. end;
  605. procedure TIdThreadSafeBoolean.SetValue(const AValue: Boolean);
  606. begin
  607. Lock;
  608. try
  609. FValue := AValue;
  610. finally
  611. Unlock;
  612. end;
  613. end;
  614. function TIdThreadSafeBoolean.Toggle: Boolean;
  615. begin
  616. Lock;
  617. try
  618. FValue := not FValue;
  619. Result := FValue;
  620. finally
  621. Unlock;
  622. end;
  623. end;
  624. { TIdThreadSafeDateTime }
  625. procedure TIdThreadSafeDateTime.Add(const AValue: TDateTime);
  626. begin
  627. Lock;
  628. try
  629. FValue := FValue + AValue;
  630. finally
  631. Unlock;
  632. end;
  633. end;
  634. function TIdThreadSafeDateTime.GetValue: TDateTime;
  635. begin
  636. Lock;
  637. try
  638. Result := FValue;
  639. finally
  640. Unlock;
  641. end;
  642. end;
  643. procedure TIdThreadSafeDateTime.SetValue(const AValue: TDateTime);
  644. begin
  645. Lock;
  646. try
  647. FValue := AValue;
  648. finally
  649. Unlock;
  650. end;
  651. end;
  652. procedure TIdThreadSafeDateTime.Subtract(const AValue: TDateTime);
  653. begin
  654. Lock;
  655. try
  656. FValue := FValue - AValue;
  657. finally
  658. Unlock;
  659. end;
  660. end;
  661. { TIdThreadSafeDouble }
  662. procedure TIdThreadSafeDouble.Add(const AValue: Double);
  663. begin
  664. Lock;
  665. try
  666. FValue := FValue + AValue;
  667. finally
  668. Unlock;
  669. end;
  670. end;
  671. function TIdThreadSafeDouble.GetValue: Double;
  672. begin
  673. Lock;
  674. try
  675. Result := FValue;
  676. finally
  677. Unlock;
  678. end;
  679. end;
  680. procedure TIdThreadSafeDouble.SetValue(const AValue: Double);
  681. begin
  682. Lock;
  683. try
  684. FValue := AValue;
  685. finally
  686. Unlock;
  687. end;
  688. end;
  689. procedure TIdThreadSafeDouble.Subtract(const AValue: Double);
  690. begin
  691. Lock;
  692. try
  693. FValue := FValue - AValue;
  694. finally
  695. Unlock;
  696. end;
  697. end;
  698. { TIdThreadSafeInt64 }
  699. function TIdThreadSafeInt64.Decrement(const AValue: Int64 = 1): Int64;
  700. begin
  701. Lock;
  702. try
  703. Result := FValue;
  704. Dec(FValue, AValue);
  705. finally
  706. Unlock;
  707. end;
  708. end;
  709. function TIdThreadSafeInt64.GetValue: Int64;
  710. begin
  711. Lock;
  712. try
  713. Result := FValue;
  714. finally
  715. Unlock;
  716. end;
  717. end;
  718. function TIdThreadSafeInt64.Increment(const AValue: Int64 = 1): Int64;
  719. begin
  720. Lock;
  721. try
  722. Result := FValue;
  723. Inc(FValue, AValue);
  724. finally
  725. Unlock;
  726. end;
  727. end;
  728. procedure TIdThreadSafeInt64.SetValue(const AValue: Int64);
  729. begin
  730. Lock;
  731. try
  732. FValue := AValue;
  733. finally
  734. Unlock;
  735. end;
  736. end;
  737. { TIdThreadSafeUInt64 }
  738. function TIdThreadSafeUInt64.Decrement(const AValue: UInt64 = 1): UInt64;
  739. begin
  740. Lock;
  741. try
  742. Result := FValue;
  743. Dec(FValue, AValue);
  744. finally
  745. Unlock;
  746. end;
  747. end;
  748. function TIdThreadSafeUInt64.GetValue: UInt64;
  749. begin
  750. Lock;
  751. try
  752. Result := FValue;
  753. finally
  754. Unlock;
  755. end;
  756. end;
  757. function TIdThreadSafeUInt64.Increment(const AValue: UInt64 = 1): UInt64;
  758. begin
  759. Lock;
  760. try
  761. Result := FValue;
  762. Inc(FValue, AValue);
  763. finally
  764. Unlock;
  765. end;
  766. end;
  767. procedure TIdThreadSafeUInt64.SetValue(const AValue: UInt64);
  768. begin
  769. Lock;
  770. try
  771. FValue := AValue;
  772. finally
  773. Unlock;
  774. end;
  775. end;
  776. end.