IdThreadSafe.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  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. TIdThreadSafeInteger = class(TIdThreadSafe)
  65. protected
  66. FValue: Integer;
  67. //
  68. function GetValue: Integer;
  69. procedure SetValue(const AValue: Integer);
  70. public
  71. function Decrement: Integer; overload;
  72. function Decrement(const AValue : Integer) : Integer; overload;
  73. function Increment: Integer; overload;
  74. function Increment(const AValue : Integer) : Integer; overload;
  75. //
  76. property Value: Integer read GetValue write SetValue;
  77. end;
  78. TIdThreadSafeInt32 = TIdThreadSafeInteger;
  79. TIdThreadSafeBoolean = class(TIdThreadSafe)
  80. protected
  81. FValue: Boolean;
  82. //
  83. function GetValue: Boolean;
  84. procedure SetValue(const AValue: Boolean);
  85. public
  86. function Toggle: Boolean;
  87. //
  88. property Value: Boolean read GetValue write SetValue;
  89. end;
  90. TIdThreadSafeCardinal = class(TIdThreadSafe)
  91. protected
  92. FValue: Cardinal;
  93. //
  94. function GetValue: Cardinal;
  95. procedure SetValue(const AValue: Cardinal);
  96. public
  97. function Decrement: Cardinal; overload;
  98. function Decrement(const AValue : Cardinal) : Cardinal; overload;
  99. function Increment: Cardinal; overload;
  100. function Increment(const AValue : Cardinal) : Cardinal; overload;
  101. //
  102. property Value: Cardinal read GetValue write SetValue;
  103. end;
  104. TIdThreadSafeUInt32 = TIdThreadSafeCardinal;
  105. TIdThreadSafeInt64 = class(TIdThreadSafe)
  106. protected
  107. FValue: Int64;
  108. //
  109. function GetValue: Int64;
  110. procedure SetValue(const AValue: Int64);
  111. public
  112. function Decrement: Int64; overload;
  113. function Decrement(const AValue : Int64) : Int64; overload;
  114. function Increment: Int64; overload;
  115. function Increment(const AValue : Int64) : Int64; overload;
  116. //
  117. property Value: Int64 read GetValue write SetValue;
  118. end;
  119. TIdThreadSafeString = class(TIdThreadSafe)
  120. protected
  121. FValue: string;
  122. //
  123. function GetValue: string;
  124. procedure SetValue(const AValue: string);
  125. public
  126. procedure Append(const AValue: string);
  127. procedure Prepend(const AValue: string);
  128. //
  129. property Value: string read GetValue write SetValue;
  130. end;
  131. TIdThreadSafeStringList = class(TIdThreadSafe)
  132. protected
  133. FValue: TStringList;
  134. //
  135. function GetValue(const AName: string): string;
  136. procedure SetValue(const AName, AValue: string);
  137. public
  138. constructor Create; override;
  139. destructor Destroy; override;
  140. procedure Add(const AItem: string);
  141. procedure AddObject(const AItem: string; AObject: TObject);
  142. procedure Clear;
  143. function Empty: Boolean;
  144. function Lock: TStringList; reintroduce;
  145. function ObjectByItem(const AItem: string): TObject;
  146. procedure Remove(const AItem: string);
  147. procedure Unlock; reintroduce;
  148. property Values[const AName: string]: string read GetValue write SetValue;
  149. end;
  150. TIdThreadSafeDateTime = class(TIdThreadSafe)
  151. protected
  152. FValue : TDateTime;
  153. function GetValue: TDateTime;
  154. procedure SetValue(const AValue: TDateTime);
  155. public
  156. procedure Add(const AValue : TDateTime);
  157. procedure Subtract(const AValue : TDateTime);
  158. property Value: TDateTime read GetValue write SetValue;
  159. end;
  160. //In D7, a double is the same as a TDateTime. In DotNET, it is not.
  161. TIdThreadSafeDouble = class(TIdThreadSafe)
  162. protected
  163. FValue : Double;
  164. function GetValue: Double;
  165. procedure SetValue(const AValue: Double);
  166. public
  167. procedure Add(const AValue : Double);
  168. procedure Subtract(const AValue : Double);
  169. property Value: Double read GetValue write SetValue;
  170. end;
  171. //TODO: Later make this descend from TIdThreadSafe instead
  172. {$IFDEF HAS_GENERICS_TThreadList}
  173. TIdThreadSafeList<T> = class(TThreadList<T>)
  174. {$ELSE}
  175. TIdThreadSafeList = class(TThreadList)
  176. {$ENDIF}
  177. public
  178. procedure Assign(AThreadList: TThreadList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF});overload;
  179. procedure Assign(AList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF});overload;
  180. // Here to make it virtual
  181. constructor Create; virtual;
  182. function IsCountLessThan(const AValue: UInt32): Boolean;
  183. function Count:Integer;
  184. function IsEmpty: Boolean;
  185. function Pop: {$IFDEF HAS_GENERICS_TThreadList}T{$ELSE}Pointer{$ENDIF};
  186. function Pull: {$IFDEF HAS_GENERICS_TThreadList}T{$ELSE}Pointer{$ENDIF};
  187. end;
  188. {$IFDEF HAS_GENERICS_TObjectList}
  189. TIdThreadSafeObjectList<T: class> = class(TIdThreadSafeList<T>)
  190. {$ELSE}
  191. TIdThreadSafeObjectList = class(TIdThreadSafeList)
  192. {$ENDIF}
  193. {$IFNDEF USE_OBJECT_ARC}
  194. private
  195. FOwnsObjects: Boolean;
  196. {$ENDIF}
  197. public
  198. {$IFNDEF USE_OBJECT_ARC}
  199. constructor Create; override;
  200. destructor Destroy; override;
  201. {$ENDIF}
  202. procedure ClearAndFree;
  203. {$IFNDEF USE_OBJECT_ARC}
  204. property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
  205. {$ENDIF}
  206. end;
  207. implementation
  208. uses
  209. {$IFDEF VCL_2010_OR_ABOVE}
  210. {$IFDEF WINDOWS}
  211. Windows,
  212. {$ENDIF}
  213. {$ENDIF}
  214. {$IFDEF VCL_XE3_OR_ABOVE}
  215. System.SyncObjs,
  216. {$ENDIF}
  217. SysUtils;
  218. { TIdThreadSafe }
  219. constructor TIdThreadSafe.Create;
  220. begin
  221. inherited Create;
  222. FCriticalSection := TIdCriticalSection.Create;
  223. end;
  224. destructor TIdThreadSafe.Destroy;
  225. begin
  226. FreeAndNil(FCriticalSection);
  227. inherited Destroy;
  228. end;
  229. procedure TIdThreadSafe.Lock;
  230. begin
  231. FCriticalSection.Enter;
  232. end;
  233. procedure TIdThreadSafe.Unlock;
  234. begin
  235. FCriticalSection.Leave;
  236. end;
  237. { TIdThreadSafeInteger }
  238. function TIdThreadSafeInteger.Decrement: Integer;
  239. begin
  240. Lock;
  241. try
  242. Result := FValue;
  243. Dec(FValue);
  244. finally
  245. Unlock;
  246. end;
  247. end;
  248. function TIdThreadSafeInteger.Decrement(const AValue: Integer): Integer;
  249. begin
  250. Lock;
  251. try
  252. Result := FValue;
  253. Dec(FValue,AValue);
  254. finally
  255. Unlock;
  256. end;
  257. end;
  258. function TIdThreadSafeInteger.GetValue: Integer;
  259. begin
  260. Lock;
  261. try
  262. Result := FValue;
  263. finally
  264. Unlock;
  265. end;
  266. end;
  267. function TIdThreadSafeInteger.Increment: Integer;
  268. begin
  269. Lock;
  270. try
  271. Result := FValue;
  272. Inc(FValue);
  273. finally
  274. Unlock;
  275. end;
  276. end;
  277. function TIdThreadSafeInteger.Increment(const AValue: Integer): Integer;
  278. begin
  279. Lock;
  280. try
  281. Result := FValue;
  282. Inc(FValue,AValue);
  283. finally
  284. Unlock;
  285. end;
  286. end;
  287. procedure TIdThreadSafeInteger.SetValue(const AValue: Integer);
  288. begin
  289. Lock;
  290. try
  291. FValue := AValue;
  292. finally
  293. Unlock;
  294. end;
  295. end;
  296. { TIdThreadSafeString }
  297. procedure TIdThreadSafeString.Append(const AValue: string);
  298. begin
  299. Lock;
  300. try
  301. FValue := FValue + AValue;
  302. finally
  303. Unlock;
  304. end;
  305. end;
  306. function TIdThreadSafeString.GetValue: string;
  307. begin
  308. Lock;
  309. try
  310. Result := FValue;
  311. finally
  312. Unlock;
  313. end;
  314. end;
  315. procedure TIdThreadSafeString.Prepend(const AValue: string);
  316. begin
  317. Lock;
  318. try
  319. FValue := AValue + FValue;
  320. finally
  321. Unlock;
  322. end;
  323. end;
  324. procedure TIdThreadSafeString.SetValue(const AValue: string);
  325. begin
  326. Lock;
  327. try
  328. FValue := AValue;
  329. finally
  330. Unlock;
  331. end;
  332. end;
  333. { TIdThreadSafeStringList }
  334. procedure TIdThreadSafeStringList.Add(const AItem: string);
  335. begin
  336. Lock;
  337. try
  338. FValue.Add(AItem);
  339. finally
  340. Unlock;
  341. end;
  342. end;
  343. procedure TIdThreadSafeStringList.AddObject(const AItem: string; AObject: TObject);
  344. begin
  345. Lock;
  346. try
  347. FValue.AddObject(AItem, AObject);
  348. finally
  349. Unlock;
  350. end;
  351. end;
  352. procedure TIdThreadSafeStringList.Clear;
  353. begin
  354. Lock;
  355. try
  356. FValue.Clear;
  357. finally
  358. Unlock;
  359. end;
  360. end;
  361. constructor TIdThreadSafeStringList.Create;
  362. begin
  363. inherited Create;
  364. FValue := TStringList.Create;
  365. end;
  366. destructor TIdThreadSafeStringList.Destroy;
  367. begin
  368. inherited Lock;
  369. try
  370. FreeAndNil(FValue);
  371. finally
  372. inherited Unlock;
  373. end;
  374. inherited Destroy;
  375. end;
  376. function TIdThreadSafeStringList.Empty: Boolean;
  377. begin
  378. Lock;
  379. try
  380. Result := FValue.Count = 0;
  381. finally Unlock; end;
  382. end;
  383. function TIdThreadSafeStringList.GetValue(const AName: string): string;
  384. begin
  385. Lock;
  386. try
  387. Result := FValue.Values[AName];
  388. finally
  389. Unlock;
  390. end;
  391. end;
  392. function TIdThreadSafeStringList.Lock: TStringList;
  393. begin
  394. inherited Lock;
  395. Result := FValue;
  396. end;
  397. function TIdThreadSafeStringList.ObjectByItem(const AItem: string): TObject;
  398. var
  399. i: Integer;
  400. begin
  401. Result := nil;
  402. Lock;
  403. try
  404. i := FValue.IndexOf(AItem);
  405. if i > -1 then begin
  406. Result := FValue.Objects[i];
  407. end;
  408. finally
  409. Unlock;
  410. end;
  411. end;
  412. procedure TIdThreadSafeStringList.Remove(const AItem: string);
  413. var
  414. i: Integer;
  415. begin
  416. Lock;
  417. try
  418. i := FValue.IndexOf(AItem);
  419. if i > -1 then begin
  420. FValue.Delete(i);
  421. end;
  422. finally
  423. Unlock;
  424. end;
  425. end;
  426. procedure TIdThreadSafeStringList.SetValue(const AName, AValue: string);
  427. begin
  428. Lock;
  429. try
  430. FValue.Values[AName] := AValue;
  431. finally
  432. Unlock;
  433. end;
  434. end;
  435. procedure TIdThreadSafeStringList.Unlock;
  436. begin
  437. inherited Unlock;
  438. end;
  439. { TIdThreadSafeCardinal }
  440. function TIdThreadSafeCardinal.Decrement: Cardinal;
  441. begin
  442. Lock;
  443. try
  444. Result := FValue;
  445. Dec(FValue);
  446. finally
  447. Unlock;
  448. end;
  449. end;
  450. function TIdThreadSafeCardinal.Decrement(const AValue: Cardinal): Cardinal;
  451. begin
  452. Lock;
  453. try
  454. Result := FValue;
  455. Dec(FValue,AValue);
  456. finally
  457. Unlock;
  458. end;
  459. end;
  460. function TIdThreadSafeCardinal.GetValue: Cardinal;
  461. begin
  462. Lock;
  463. try
  464. Result := FValue;
  465. finally
  466. Unlock;
  467. end;
  468. end;
  469. function TIdThreadSafeCardinal.Increment: Cardinal;
  470. begin
  471. Lock;
  472. try
  473. Result := FValue;
  474. Inc(FValue);
  475. finally
  476. Unlock;
  477. end;
  478. end;
  479. function TIdThreadSafeCardinal.Increment(const AValue: Cardinal): Cardinal;
  480. begin
  481. Lock;
  482. try
  483. Result := FValue;
  484. Inc(FValue,AValue);
  485. finally
  486. Unlock;
  487. end;
  488. end;
  489. procedure TIdThreadSafeCardinal.SetValue(const AValue: Cardinal);
  490. begin
  491. Lock;
  492. try
  493. FValue := AValue;
  494. finally
  495. Unlock;
  496. end;
  497. end;
  498. { TIdThreadSafeList }
  499. function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.IsCountLessThan(const AValue: UInt32): Boolean;
  500. begin
  501. if Assigned(Self) then begin
  502. Result := UInt32(Count) < AValue;
  503. end else begin
  504. Result := True; // none always <
  505. end;
  506. end;
  507. function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.IsEmpty: Boolean;
  508. begin
  509. Result := IsCountLessThan(1);
  510. end;
  511. {$IFDEF HAS_GENERICS_TThreadList}
  512. function TIdThreadSafeList<T>.Pop: T;
  513. {$ELSE}
  514. function TIdThreadSafeList.Pop: Pointer;
  515. {$ENDIF}
  516. var
  517. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  518. begin
  519. LList := LockList;
  520. try
  521. if LList.Count > 0 then begin
  522. Result := LList.Items[Count - 1];
  523. LList.Delete(Count - 1);
  524. end else begin
  525. Result := {$IFDEF HAS_GENERICS_TThreadList}Default(T){$ELSE}nil{$ENDIF};
  526. end;
  527. finally
  528. UnlockList;
  529. end;
  530. end;
  531. {$IFDEF HAS_GENERICS_TThreadList}
  532. function TIdThreadSafeList<T>.Pull: T;
  533. {$ELSE}
  534. function TIdThreadSafeList.Pull: Pointer;
  535. {$ENDIF}
  536. var
  537. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  538. begin
  539. LList := LockList;
  540. try
  541. if LList.Count > 0 then begin
  542. Result := LList.Items[0];
  543. LList.Delete(0);
  544. end else begin
  545. Result := {$IFDEF HAS_GENERICS_TThreadList}Default(T){$ELSE}nil{$ENDIF};
  546. end;
  547. finally
  548. UnlockList;
  549. end;
  550. end;
  551. {$IFDEF HAS_GENERICS_TThreadList}
  552. procedure TIdThreadSafeList<T>.Assign(AList: TList<T>);
  553. {$ELSE}
  554. procedure TIdThreadSafeList.Assign(AList: TList);
  555. {$ENDIF}
  556. var
  557. i: integer;
  558. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  559. begin
  560. LList := LockList;
  561. try
  562. LList.Clear;
  563. LList.Capacity := AList.Capacity;
  564. for i := 0 to AList.Count - 1 do begin
  565. LList.Add(AList.Items[i]);
  566. end;
  567. finally
  568. UnlockList;
  569. end;
  570. end;
  571. {$IFDEF HAS_GENERICS_TThreadList}
  572. procedure TIdThreadSafeList<T>.Assign(AThreadList: TThreadList<T>);
  573. {$ELSE}
  574. procedure TIdThreadSafeList.Assign(AThreadList: TThreadList);
  575. {$ENDIF}
  576. var
  577. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  578. begin
  579. LList := AThreadList.LockList;
  580. try
  581. Assign(LList);
  582. finally
  583. AThreadList.UnlockList;
  584. end;
  585. end;
  586. constructor TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.Create;
  587. begin
  588. inherited Create;
  589. end;
  590. function TIdThreadSafeList{$IFDEF HAS_GENERICS_TThreadList}<T>{$ENDIF}.Count: Integer;
  591. var
  592. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  593. begin
  594. LList := LockList;
  595. try
  596. Result := LList.Count;
  597. finally
  598. UnlockList;
  599. end;
  600. end;
  601. { TIdThreadSafeObjectList }
  602. {$IFNDEF USE_OBJECT_ARC}
  603. constructor TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.Create;
  604. begin
  605. inherited Create;
  606. OwnsObjects := False;
  607. end;
  608. destructor TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.Destroy;
  609. begin
  610. if OwnsObjects then ClearAndFree;
  611. inherited;
  612. end;
  613. {$ENDIF}
  614. procedure TIdThreadSafeObjectList{$IFDEF HAS_GENERICS_TObjectList}<T>{$ENDIF}.ClearAndFree;
  615. var
  616. LList: TList{$IFDEF HAS_GENERICS_TList}<T>{$ENDIF};
  617. i: Integer;
  618. begin
  619. LList := LockList;
  620. try
  621. {$IFNDEF USE_OBJECT_ARC}
  622. for i := 0 to LList.Count-1 do begin
  623. {$IFDEF HAS_GENERICS_TList}LList[i]{$ELSE}TObject(LList[i]){$ENDIF}.Free;
  624. end;
  625. {$ENDIF}
  626. LList.Clear;
  627. finally
  628. UnlockList;
  629. end;
  630. end;
  631. { TIdThreadSafeBoolean }
  632. function TIdThreadSafeBoolean.GetValue: Boolean;
  633. begin
  634. Lock;
  635. try
  636. Result := FValue;
  637. finally
  638. Unlock;
  639. end;
  640. end;
  641. procedure TIdThreadSafeBoolean.SetValue(const AValue: Boolean);
  642. begin
  643. Lock;
  644. try
  645. FValue := AValue;
  646. finally
  647. Unlock;
  648. end;
  649. end;
  650. function TIdThreadSafeBoolean.Toggle: Boolean;
  651. begin
  652. Lock;
  653. try
  654. FValue := not FValue;
  655. Result := FValue;
  656. finally
  657. Unlock;
  658. end;
  659. end;
  660. { TIdThreadSafeDateTime }
  661. procedure TIdThreadSafeDateTime.Add(const AValue: TDateTime);
  662. begin
  663. Lock;
  664. try
  665. FValue := FValue + AValue;
  666. finally
  667. Unlock;
  668. end;
  669. end;
  670. function TIdThreadSafeDateTime.GetValue: TDateTime;
  671. begin
  672. Lock;
  673. try
  674. Result := FValue;
  675. finally
  676. Unlock;
  677. end;
  678. end;
  679. procedure TIdThreadSafeDateTime.SetValue(const AValue: TDateTime);
  680. begin
  681. Lock;
  682. try
  683. FValue := AValue;
  684. finally
  685. Unlock;
  686. end;
  687. end;
  688. procedure TIdThreadSafeDateTime.Subtract(const AValue: TDateTime);
  689. begin
  690. Lock;
  691. try
  692. FValue := FValue - AValue;
  693. finally
  694. Unlock;
  695. end;
  696. end;
  697. { TIdThreadSafeDouble }
  698. procedure TIdThreadSafeDouble.Add(const AValue: Double);
  699. begin
  700. Lock;
  701. try
  702. FValue := FValue + AValue;
  703. finally
  704. Unlock;
  705. end;
  706. end;
  707. function TIdThreadSafeDouble.GetValue: Double;
  708. begin
  709. Lock;
  710. try
  711. Result := FValue;
  712. finally
  713. Unlock;
  714. end;
  715. end;
  716. procedure TIdThreadSafeDouble.SetValue(const AValue: Double);
  717. begin
  718. Lock;
  719. try
  720. FValue := AValue;
  721. finally
  722. Unlock;
  723. end;
  724. end;
  725. procedure TIdThreadSafeDouble.Subtract(const AValue: Double);
  726. begin
  727. Lock;
  728. try
  729. FValue := FValue - AValue;
  730. finally
  731. Unlock;
  732. end;
  733. end;
  734. { TIdThreadSafeInt64 }
  735. function TIdThreadSafeInt64.Decrement(const AValue: Int64): Int64;
  736. begin
  737. Lock;
  738. try
  739. Result := FValue;
  740. Dec(FValue,AValue);
  741. finally
  742. Unlock;
  743. end;
  744. end;
  745. function TIdThreadSafeInt64.Decrement: Int64;
  746. begin
  747. Lock;
  748. try
  749. Result := FValue;
  750. Dec(FValue);
  751. finally
  752. Unlock;
  753. end;
  754. end;
  755. function TIdThreadSafeInt64.GetValue: Int64;
  756. begin
  757. Lock;
  758. try
  759. Result := FValue;
  760. finally
  761. Unlock;
  762. end;
  763. end;
  764. function TIdThreadSafeInt64.Increment(const AValue: Int64): Int64;
  765. begin
  766. Lock;
  767. try
  768. Result := FValue;
  769. Inc(FValue,AValue);
  770. finally
  771. Unlock;
  772. end;
  773. end;
  774. function TIdThreadSafeInt64.Increment: Int64;
  775. begin
  776. Lock;
  777. try
  778. Result := FValue;
  779. Inc(FValue);
  780. finally
  781. Unlock;
  782. end;
  783. end;
  784. procedure TIdThreadSafeInt64.SetValue(const AValue: Int64);
  785. begin
  786. Lock;
  787. try
  788. FValue := AValue;
  789. finally
  790. Unlock;
  791. end;
  792. end;
  793. end.