25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
1.7 KiB

  1. unit uutlSyncObjs;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, syncobjs;
  6. type
  7. TAutoResetEvent = class(TEvent)
  8. public
  9. constructor Create(aInitial: boolean = false);
  10. end;
  11. // aliased to stay in LCL naming scheme for TSimpleEvent
  12. TutlAutoResetEvent = TAutoResetEvent;
  13. TutlSpinLock = class
  14. private
  15. fLock: DWord;
  16. fLockReused: integer;
  17. public
  18. constructor Create;
  19. destructor Destroy; override;
  20. procedure Enter;
  21. procedure Leave;
  22. end;
  23. implementation
  24. { TAutoResetEvent }
  25. constructor TAutoResetEvent.Create(aInitial: boolean);
  26. begin
  27. inherited Create(Nil, false, aInitial, '');
  28. end;
  29. { TutlSpinLock }
  30. constructor TutlSpinLock.Create;
  31. begin
  32. inherited Create;
  33. fLock:= 0;
  34. fLockReused:= 0;
  35. end;
  36. destructor TutlSpinLock.Destroy;
  37. begin
  38. Enter;
  39. inherited Destroy;
  40. end;
  41. procedure TutlSpinLock.Enter;
  42. var
  43. ti: dword;
  44. begin
  45. ti:= ThreadID;
  46. if ti = InterlockedCompareExchange(fLock, ti, ti) then begin
  47. {
  48. The lock is already held by this thread. This means it cannot be modified by a concurrent
  49. operation (assuming Enter/Leave bracket correctly), and we can act non-atomar on other variables.
  50. }
  51. inc(fLockReused);
  52. end else begin
  53. while InterlockedCompareExchange(fLock, ti, 0) <> 0 do ;
  54. end;
  55. end;
  56. procedure TutlSpinLock.Leave;
  57. var
  58. ti: DWord;
  59. begin
  60. ti:= ThreadID;
  61. // Unlock only if we hold the lock
  62. if ti = InterlockedCompareExchange(fLock, ti, ti) then begin
  63. // our lock, but we haven't yet done anything (note the above is essentially a threadsafe CMP if successful)
  64. if fLockReused = 0 then
  65. InterLockedExchange(fLock, 0) // normal lock
  66. else
  67. dec(fLockReused); // nested locks
  68. end;
  69. end;
  70. end.