Changeset 142 for MicroThreading/UMicroThreading.pas
- Timestamp:
- Jan 24, 2011, 4:02:40 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
MicroThreading/UMicroThreading.pas
r141 r142 11 11 Classes, SysUtils, Contnrs, SyncObjs, DateUtils, Dialogs, Forms; 12 12 13 const 14 DefaultStackSize = $4000; 15 13 16 type 14 17 TMicroThread = class; 15 18 TMicroThreadScheduler = class; 16 19 17 TStartEvent = procedure(MicroThread: TMicroThread) of object; 18 19 TMicroThreadState = (tsReady, tsRunning, tsWaiting, tsBlocked, tsSuspended, 20 tsSleeping, tsFinished); 20 TMicroThreadState = (tsWaiting, tsRunning, tsBlocked, tsSuspended, 21 tsSleeping); 22 21 23 22 24 { TMicroThread } … … 24 26 TMicroThread = class 25 27 private 26 F Method: TStartEvent;28 FFreeOnTerminate: Boolean; 27 29 FStack: Pointer; 28 30 FStackSize: Integer; … … 33 35 FBasePointer: Pointer; 34 36 FWakeupTime: TDateTime; 37 FTerminated: Boolean; 38 FExecuted: Boolean; // At first go through Execute method, then switch context 39 FFinished: Boolean; 35 40 public 36 41 Id: Integer; … … 39 44 State: TMicroThreadState; 40 45 Scheduler: TMicroThreadScheduler; 46 procedure Execute; virtual; 47 48 // Internal execution 41 49 procedure Yield; 42 50 procedure Sleep(Duration: TDateTime); 43 constructor Create; 51 function WaitForSignal(Signal: TEvent): TWaitResult; 52 53 // External execution 54 procedure WaitFor; 55 procedure Terminate; 56 procedure Start; 57 procedure Stop; 58 59 constructor Create(CreateSuspended: Boolean; 60 const StackSize: SizeUInt = DefaultStackSize); 44 61 destructor Destroy; override; 45 property Method: TStartEvent read FMethod write FMethod;46 62 property ExecutionTime: TDateTime read FExecutionTime; 63 property FreeOnTerminate: Boolean read FFreeOnTerminate 64 write FFreeOnTerminate; 65 property Terminated: Boolean read FTerminated; 66 end; 67 68 TMicroThreadEvent = procedure(MicroThread: TMicroThread) of object; 69 70 { TMicroThreadMethod } 71 72 TMicroThreadMethod = class(TMicroThread) 73 Method: TMicroThreadEvent; 74 procedure Execute; override; 47 75 end; 48 76 … … 55 83 TMicroThreadScheduler = class 56 84 private 57 FFreeMicroThreadOnFinish: Boolean;58 85 ThreadPool: TThreadPool; 59 86 RoundRobinIndex: Integer; … … 67 94 FExecutedCount: Integer; 68 95 FTerminated: Boolean; 96 FThreadPoolSize: Integer; 69 97 function GetMicroThreadCount: Integer; 98 function GetThreadPoolSize: Integer; 99 procedure SetThreadPoolSize(const AValue: Integer); 70 100 procedure Yield(MicroThread: TMicroThread); 71 101 public 72 102 MicroThreads: TObjectList; // TList<TMicroThread> 73 103 Lock: TCriticalSection; 104 CurrentMicroThread: TMicroThread; 74 105 function GetNow: TDateTime; 75 function Add(Name: string; Method: TStartEvent): TMicroThread; 106 function Add(MicroThread: TMicroThread): Integer; 107 function AddMethod(Method: TMicroThreadEvent): Integer; 76 108 constructor Create; 77 109 destructor Destroy; override; … … 80 112 procedure Stop; 81 113 property MicroThreadCount: Integer read GetMicroThreadCount; 82 property FreeMicroThreadOnFinish: Boolean read FFreeMicroThreadOnFinish 83 write FFreeMicroThreadOnFinish; 84 end; 114 property ThreadPoolSize: Integer read GetThreadPoolSize 115 write SetThreadPoolSize; 116 end; 117 118 var 119 MainScheduler: TMicroThreadScheduler; 85 120 86 121 const 87 MicroThreadStateText: array[TMicroThreadState] of string = (' Ready', 'Running',88 ' Waiting', 'Blocked', 'Suspended', 'Sleeping', 'Finished');122 MicroThreadStateText: array[TMicroThreadState] of string = ('Waiting', 123 'Running', 'Blocked', 'Suspended', 'Sleeping'); 89 124 90 125 implementation 91 126 127 { TMicroThreadMethod } 128 129 procedure TMicroThreadMethod.Execute; 130 begin 131 inherited Execute; 132 Method(Self); 133 end; 134 92 135 93 136 { TMicroThread } 94 137 138 procedure TMicroThread.Execute; 139 begin 140 141 end; 142 95 143 procedure TMicroThread.Yield; 96 144 begin 97 145 Scheduler.Yield(Self); 146 end; 147 148 procedure TMicroThread.WaitFor; 149 begin 150 while not FFinished do begin 151 Sleep(1); 152 end; 98 153 end; 99 154 … … 105 160 end; 106 161 107 constructor TMicroThread.Create; 108 begin 109 FStackSize := $10000; 162 function TMicroThread.WaitForSignal(Signal: TEvent): TWaitResult; 163 begin 164 repeat 165 Result := Signal.WaitFor(1); 166 Sleep(1); 167 until Result <> wrTimeout; 168 end; 169 170 constructor TMicroThread.Create(CreateSuspended: Boolean; 171 const StackSize: SizeUInt = DefaultStackSize); 172 begin 173 FStackSize := StackSize; 110 174 FStack := GetMem(FStackSize); 111 175 FBasePointer := FStack + FStackSize; 112 176 FStackPointer := FBasePointer - 20; 113 177 FExecutionTime := 0; 178 FTerminated := False; 179 if CreateSuspended then 180 State := tsSuspended; 181 FFreeOnTerminate := True; 182 end; 183 184 procedure TMicroThread.Terminate; 185 begin 186 FTerminated := True; 114 187 end; 115 188 116 189 destructor TMicroThread.Destroy; 117 190 begin 191 Terminate; 192 WaitFor; 193 // Microthread is finished, remove it from queue 194 try 195 Scheduler.Lock.Acquire; 196 Scheduler.MicroThreads.Delete(Scheduler.MicroThreads.IndexOf(Self)); 197 finally 198 Scheduler.Lock.Release; 199 end; 118 200 FreeMem(FStack); 119 201 inherited Destroy; 202 end; 203 204 procedure TMicroThread.Start; 205 begin 206 State := tsWaiting; 207 end; 208 209 procedure TMicroThread.Stop; 210 begin 211 State := tsSuspended; 120 212 end; 121 213 … … 142 234 end; 143 235 144 function TMicroThreadScheduler.Add(Name: string; Method: TStartEvent 145 ): TMicroThread; 146 var 147 NewMicroThread: TMicroThread; 148 begin 149 NewMicroThread := TMicroThread.Create; 236 function TMicroThreadScheduler.Add(MicroThread: TMicroThread): Integer; 237 begin 238 Inc(LastId); 239 MicroThread.Scheduler := Self; 240 MicroThread.Id := LastId; 241 Result := MicroThreads.Add(MicroThread); 242 end; 243 244 function TMicroThreadScheduler.AddMethod(Method: TMicroThreadEvent): Integer; 245 var 246 NewMicroThread: TMicroThreadMethod; 247 begin 248 NewMicroThread := TMicroThreadMethod.Create(False); 249 NewMicroThread.Method := Method; 150 250 NewMicroThread.Scheduler := Self; 151 NewMicroThread.Name := Name; 152 NewMicroThread.Method := Method; 153 Inc(LastId); 154 NewMicroThread.Id := LastId; 155 MicroThreads.Add(NewMicroThread); 251 Result := Add(NewMicroThread); 156 252 end; 157 253 … … 161 257 MicroThreads := TObjectList.Create; 162 258 ThreadPool := TThreadPool.Create; 163 FFreeMicroThreadOnFinish := True;164 259 {$IFDEF Windows} 165 260 QueryPerformanceFrequency(FFrequency); … … 235 330 mov ebp, edx 236 331 end; 332 CurrentMicroThread := nil; 237 333 end; 238 334 … … 245 341 if RoundRobinIndex >= MicroThreads.Count then 246 342 RoundRobinIndex := 0; 247 while (I < MicroThreads.Count) and (TMicroThread(MicroThreads[RoundRobinIndex]).State <> tsReady) and248 (TMicroThread(MicroThreads[RoundRobinIndex]).State <> tsWaiting) do begin343 while (I < MicroThreads.Count) and 344 (TMicroThread(MicroThreads[RoundRobinIndex]).State <> tsWaiting) do begin 249 345 // WakeUp sleeping threads 250 346 if (TMicroThread(MicroThreads[RoundRobinIndex]).State = tsSleeping) and … … 268 364 if Assigned(FSelected) and (FExecutedCount < FExecuteCount) then begin 269 365 Inc(FExecutedCount); 366 CurrentMicroThread := FSelected; 270 367 asm 271 368 // Store scheduler stack … … 276 373 mov [eax].TMicroThreadScheduler.FMainBasePointer, edx 277 374 end; 278 if FSelected.State = tsReady then begin 375 if not FSelected.FExecuted then begin 376 FSelected.FExecuted := True; 279 377 FSelected.State := tsRunning; 280 378 FSelected.FExecutionStartTime := Time; … … 293 391 mov ebp, edx 294 392 end; 295 StaticMicroThread. Method(StaticMicroThread);393 StaticMicroThread.Execute; 296 394 //FSelected.Method(FSelected); 297 395 StaticScheduler := StaticMicroThread.Scheduler; … … 307 405 FSelected.FExecutionTime := FSelected.FExecutionTime + 308 406 (FSelected.FExecutionEndTime - FSelected.FExecutionStartTime); 309 if FFreeMicroThreadOnFinish then begin 310 // Microthread is finished, remove it from queue 311 try 312 Lock.Acquire; 313 MicroThreads.Delete(MicroThreads.IndexOf(FSelected)); 314 finally 315 Lock.Release; 316 end; 317 end else FSelected.State := tsFinished; 407 FSelected.FFinished := True; 408 if FSelected.FFreeOnTerminate then begin 409 FSelected.Free; 410 end;; 318 411 end else 319 412 if FSelected.State = tsWaiting then begin … … 348 441 end; 349 442 443 function TMicroThreadScheduler.GetThreadPoolSize: Integer; 444 begin 445 Result := FThreadPoolSize; 446 end; 447 448 procedure TMicroThreadScheduler.SetThreadPoolSize(const AValue: Integer); 449 begin 450 FThreadPoolSize := AValue; 451 end; 452 453 initialization 454 455 MainScheduler := TMicroThreadScheduler.Create; 456 457 finalization 458 459 MainScheduler.Free; 460 350 461 end. 351 462
Note:
See TracChangeset
for help on using the changeset viewer.