wasm.timer.objects.pas 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. {
  2. This file is part of the Free Component Library
  3. Webassembly Timer API - Objects layer.
  4. Copyright (c) 2024 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit wasm.timer.objects;
  12. {$mode ObjFPC}{$H+}
  13. interface
  14. uses
  15. {$IFDEF FPC_DOTTEDUNITS}
  16. System.Classes, System.SysUtils, System.SyncObjs,
  17. {$ELSE}
  18. Classes, SysUtils, SyncObjs,
  19. {$ENDIF}
  20. wasm.timer.api, wasm.timer.shared;
  21. { TTimer }
  22. Type
  23. EWasmTimer = Class(Exception);
  24. { TWasmTimer }
  25. TWasmTimer = Class(TObject)
  26. Private
  27. FOnTimer : TNotifyEvent;
  28. FSender : TObject;
  29. FID : TWasmTimerID;
  30. FInterval : Integer;
  31. Public
  32. Constructor Create(aInterval : Integer; aEvent : TNotifyEvent; aSender : TObject);
  33. destructor Destroy; override;
  34. Procedure Execute;
  35. property OnTimer : TNotifyEvent Read FOnTimer;
  36. Property ID : TWasmTimerID Read FID;
  37. class procedure HandleWasmTimer(aTimerID: TWasmTimerID; userdata: pointer; var aContinue: Boolean); static;
  38. class function getPerformanceNow : Double;
  39. end;
  40. TTimer = Class(TComponent)
  41. private
  42. FTimer : TWasmTimer;
  43. FEnabled: Boolean;
  44. FInterval: Integer;
  45. FOnTimer: TNotifyEvent;
  46. procedure SetEnabled(AValue: Boolean);
  47. procedure SetInterval(AValue: Integer);
  48. procedure SetOnTimer(AValue: TNotifyEvent);
  49. protected
  50. procedure DoOnTimer(Sender: TObject); virtual;
  51. procedure CheckEnabled; virtual;
  52. procedure Loaded; override;
  53. public
  54. Destructor Destroy; override;
  55. Published
  56. Property Enabled : Boolean Read FEnabled Write SetEnabled;
  57. Property Interval : Integer Read FInterval Write SetInterval;
  58. Property OnTimer : TNotifyEvent Read FOnTimer Write SetOnTimer;
  59. end;
  60. implementation
  61. uses wasm.logger.api;
  62. resourcestring
  63. SErrCouldNotCreateTimer = 'Could not create timer';
  64. var
  65. ActiveTimers : TFPList;
  66. Lock : TCriticalSection;
  67. procedure AddTimer(aTimer : TWasmTimer);
  68. begin
  69. Lock.Enter;
  70. try
  71. ActiveTimers.Add(aTimer);
  72. finally
  73. Lock.Leave
  74. end;
  75. end;
  76. function ValidTimer(aTimer : TWasmTimer): boolean;
  77. begin
  78. Lock.Enter;
  79. try
  80. Result:=ActiveTimers.IndexOf(aTimer)<>-1;
  81. finally
  82. Lock.Leave;
  83. end;
  84. end;
  85. procedure RemoveTimer(aTimer : TWasmTimer);
  86. begin
  87. Lock.Enter;
  88. try
  89. ActiveTimers.Remove(aTimer);
  90. finally
  91. Lock.Leave;
  92. end;
  93. end;
  94. constructor TWasmTimer.Create(aInterval: Integer; aEvent: TNotifyEvent; aSender: TObject);
  95. begin
  96. FOnTimer:=aEvent;
  97. FSender:=aSender;
  98. FInterval:=aInterval;
  99. FID:=__wasm_timer_allocate(aInterval,Self);
  100. if (FID=0) then
  101. begin
  102. __wasmtimer_log(wllError,SErrCouldNotCreateTimer);
  103. Raise EWasmTimer.Create(SErrCouldNotCreateTimer);
  104. end;
  105. AddTimer(Self);
  106. end;
  107. destructor TWasmTimer.Destroy;
  108. begin
  109. FOnTimer:=Nil;
  110. RemoveTimer(Self);
  111. __wasm_timer_deallocate(FID);
  112. inherited Destroy;
  113. end;
  114. procedure TWasmTimer.Execute;
  115. begin
  116. if assigned(FOnTimer) then
  117. FOnTimer(FSender);
  118. end;
  119. class procedure TWasmTimer.HandleWasmTimer(aTimerID: TWasmTimerID; userdata: pointer; var aContinue: Boolean);
  120. var
  121. Obj : TWasmTimer absolute userdata;
  122. begin
  123. __wasmtimer_log(wllTrace, 'Timer(ID: %d) tick. Data [%p]',[aTimerID,UserData]);
  124. aContinue:=ValidTimer(Obj) and (Obj.FID=aTimerID);
  125. __wasmtimer_log(wllDebug, 'Timer(id: %d) tick. Data [%p] continue: %b',[aTimerID,UserData,aContinue]);
  126. if aContinue then
  127. Obj.Execute;
  128. end;
  129. class function TWasmTimer.getPerformanceNow: Double;
  130. begin
  131. if __wasm_timer_performance_now(@Result)<>ETIMER_SUCCESS then
  132. begin
  133. __wasmtimer_log(wllError, 'No performance timer available');
  134. Raise EWasmTimer.Create('No performance timer available');
  135. end;
  136. end;
  137. { TTimer }
  138. procedure TTimer.SetEnabled(AValue: Boolean);
  139. begin
  140. if FEnabled=AValue then Exit;
  141. FEnabled:=AValue;
  142. if csDesigning in ComponentState then
  143. exit;
  144. CheckEnabled;
  145. end;
  146. procedure TTimer.SetInterval(AValue: Integer);
  147. begin
  148. if FInterval=AValue then Exit;
  149. FInterval:=AValue;
  150. end;
  151. procedure TTimer.SetOnTimer(AValue: TNotifyEvent);
  152. begin
  153. if FOnTimer=AValue then Exit;
  154. FOnTimer:=AValue;
  155. end;
  156. procedure TTimer.DoOnTimer(Sender : TObject);
  157. begin
  158. If FEnabled and Assigned(FOnTimer) then
  159. FOnTimer(Self);
  160. end;
  161. procedure TTimer.CheckEnabled;
  162. begin
  163. if FEnabled then
  164. begin
  165. if Assigned(FTimer) or (Interval=0) then
  166. FreeAndNil(FTimer)
  167. else
  168. FTimer:=TWasmTimer.Create(Interval,@DoOnTimer,Self);
  169. end
  170. else
  171. FreeAndNil(FTimer);
  172. end;
  173. procedure TTimer.Loaded;
  174. begin
  175. inherited Loaded;
  176. CheckEnabled;
  177. end;
  178. destructor TTimer.Destroy;
  179. begin
  180. OnTimer:=Nil;
  181. Enabled:=False;
  182. inherited Destroy;
  183. end;
  184. initialization
  185. ActiveTimers:=TFPList.Create;
  186. Lock:=TCriticalSection.Create;
  187. OnWasmTimerTick:[email protected]
  188. finalization
  189. OnWasmTimerTick:=Nil;
  190. FreeAndNil(ActiveTimers);
  191. FreeAndNil(Lock);
  192. end.