Changeset 166 for MicroThreading/UMicroThreading.pas
- Timestamp:
- Feb 9, 2011, 1:35:28 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
MicroThreading/UMicroThreading.pas
r164 r166 32 32 SManagerReferenceLost = 'Reference to manager lost'; 33 33 SCantDetermineThreadID = 'Can''t determine thread for id %d'; 34 SNotInThread = 'Not in thread'; 35 SReleaseNotAcquiredLock = 'Release not acquired lock'; 34 SNotInMicroThread = 'Not in microthread'; 35 SReleaseNotAcquiredLock = 'Release on not acquired lock'; 36 SMethodNotAssigned = 'Method for microthread not assigned'; 36 37 37 38 38 39 type 40 EMicroThreadError = class(Exception); 41 39 42 TMicroThread = class; 40 43 TMicroThreadScheduler = class; … … 43 46 TMicroThreadState = (tsNone, tsWaiting, tsRunning, tsBlocked, tsSuspended); 44 47 TMicroThreadBlockState = (tbsNone, tbsSleeping, tbsWaitFor, tbsTerminating, 45 tbsTerminated );48 tbsTerminated, tbsCriticalSection); 46 49 47 50 { TMicroThreadCriticalSection } 48 51 49 52 TMicroThreadCriticalSection = class 53 private 54 FMicroThreads: TObjectList; 50 55 Lock: TCriticalSection; 51 Counter: Integer; 56 FCounter: Integer; 57 public 52 58 procedure Acquire; 53 59 procedure Release; … … 111 117 procedure Yield; 112 118 procedure MTSleep(Duration: TDateTime); // No conflicting name to global Sleep procedure 119 procedure WaitForCriticalSection(CriticalSection: TMicroThreadCriticalSection); 113 120 function WaitForEvent(Event: TMicroThreadEvent; Duration: TDateTime): TWaitResult; 114 121 procedure WaitFor; … … 141 148 142 149 TMicroThreadSimple = class(TMicroThread) 143 Method: T MicroThreadMethod;150 Method: TProcedureOfObject; 144 151 procedure Execute; override; 145 152 end; … … 228 235 BurstCount: Integer; 229 236 function Add(MicroThread: TMicroThread): Integer; 230 function AddMethod(Method: T MicroThreadMethod): Integer;237 function AddMethod(Method: TProcedureOfObject; WaitForFinish: Boolean = False): Integer; 231 238 procedure Remove(MicroThread: TMicroThread; Free: Boolean = True); 232 239 constructor Create; … … 263 270 'Running', 'Blocked', 'Suspended'); 264 271 MicroThreadBlockStateText: array[TMicroThreadBlockState] of string = ('None', 265 'Sleeping', 'WaitFor', 'Terminating', 'Terminated' );272 'Sleeping', 'WaitFor', 'Terminating', 'Terminated', 'CriticalSection'); 266 273 MicroThreadThreadStateText: array[TMicroThreadThreadState] of string = ( 267 274 'Ready', 'Running', 'Terminated'); … … 294 301 begin 295 302 MT := GetCurrentMicroThread; 296 if Assigned(MT) then Result := MT.Id else Result := -1; 303 if Assigned(MT) then Result := MT.Id 304 else Result := -1; 297 305 end; 298 306 … … 322 330 MT := GetCurrentMicroThread; 323 331 if Assigned(MT) then MT.MTSleep(Duration) 324 else Sleep(Trunc(Duration / OneMillisecond));332 else raise EMicroThreadError.Create(SNotInMicroThread); 325 333 end; 326 334 … … 332 340 Thread := TThreadEx.CurrentThread; 333 341 if Assigned(Thread) then TThread.Synchronize(Thread, Method) 334 else raise E xception.Create(Format(SCantDetermineThreadID, [GetCurrentThreadId]));342 else raise EMicroThreadError.Create(Format(SCantDetermineThreadID, [GetCurrentThreadId])); 335 343 end else Method; 336 344 end; … … 342 350 MT := GetCurrentMicroThread; 343 351 if Assigned(MT) then Result := MT.WaitForEvent(Event, Duration) 344 else begin 345 while not Event.Signaled do begin 346 Sleep(1); 347 Application.ProcessMessages; 348 end; 349 //raise Exception.Create(SNotInThread); 350 // else Result := Event.WaitFor(Trunc(Duration / OneMillisecond)); 351 end; 352 else raise EMicroThreadError.Create(SNotInMicroThread); 352 353 end; 353 354 … … 374 375 375 376 procedure TMicroThreadCriticalSection.Acquire; 376 begin 377 try 377 var 378 MT: TMicroThread; 379 Event: TMicroThreadEvent; 380 begin 381 MT := GetCurrentMicroThread; 382 if Assigned(MT) then MT.WaitForCriticalSection(Self) 383 else raise EMicroThreadError.Create(SNotInMicroThread); 384 end; 385 386 procedure TMicroThreadCriticalSection.Release; 387 begin 388 try 389 MainScheduler.FMicroThreadsLock.Acquire; 378 390 Lock.Acquire; 379 while Counter > 0 do begin 380 try 381 Lock.Release; 382 MTSleep(1 * OneMillisecond); 383 finally 384 Lock.Acquire; 385 end; 386 end; 387 Inc(Counter); 391 Dec(FCounter); 392 if FMicroThreads.Count > 0 then begin 393 // Release one waiting micro thread and lower counter 394 TMicroThread(FMicroThreads[0]).FState := tsWaiting; 395 FMicroThreads.Delete(0); 396 end; 388 397 finally 389 398 Lock.Release; 390 end; 391 end; 392 393 procedure TMicroThreadCriticalSection.Release; 394 begin 395 try 399 MainScheduler.FMicroThreadsLock.Release; 400 end; 401 end; 402 403 constructor TMicroThreadCriticalSection.Create; 404 begin 405 Lock := TCriticalSection.Create; 406 FMicroThreads := TObjectList.Create; 407 FMicroThreads.OwnsObjects := False; 408 end; 409 410 destructor TMicroThreadCriticalSection.Destroy; 411 begin 412 try 413 MainScheduler.FMicroThreadsLock.Acquire; 396 414 Lock.Acquire; 397 if Counter > 0 then Dec(Counter) 398 else raise Exception.Create(SReleaseNotAcquiredLock); 415 416 while FMicroThreads.Count > 0 do begin 417 // Release one waiting micro thread and lower counter 418 TMicroThread(FMicroThreads[0]).FState := tsWaiting; 419 FMicroThreads.Delete(0); 420 end; 399 421 finally 400 422 Lock.Release; 401 end; 402 end; 403 404 constructor TMicroThreadCriticalSection.Create; 405 begin 406 Lock := TCriticalSection.Create; 407 end; 408 409 destructor TMicroThreadCriticalSection.Destroy; 410 begin 411 Acquire; 423 MainScheduler.FMicroThreadsLock.Release; 424 end; 425 FMicroThreads.Free; 412 426 Lock.Free; 413 427 inherited Destroy; … … 456 470 MT := GetCurrentMicroThread; 457 471 if Assigned(MT) then Result := MT.WaitForEvent(Self, Duration) 458 else Result := wrSignaled;472 else raise EMicroThreadError.Create(SNotInMicroThread); 459 473 end; 460 474 … … 689 703 begin 690 704 inherited Execute; 691 Method(Self); 705 if Assigned(Method) then Method 706 else raise EMicroThreadError.Create(SMethodNotAssigned); 692 707 end; 693 708 … … 700 715 except 701 716 on E: Exception do 702 if Assigned(ExceptionHandler) then ExceptionHandler(Self, E); 717 if Assigned(ExceptionHandler) then 718 if GetCurrentThreadId = MainThreadID then ExceptionHandler(Self, E) 719 else ExceptionHandler(TThreadEx.CurrentThread, E); 703 720 end; 704 721 asm … … 745 762 procedure TMicroThread.Yield; 746 763 begin 747 if not Assigned(FManager) then748 raise Exception.Create(SManagerReferenceLost);764 // if not Assigned(FManager) then 765 // raise EMicroThreadError.Create(SManagerReferenceLost); 749 766 if FStatePending = tsNone then 750 767 FStatePending := tsWaiting; … … 774 791 FStatePending := tsBlocked; 775 792 Yield; 793 end; 794 795 procedure TMicroThread.WaitForCriticalSection( 796 CriticalSection: TMicroThreadCriticalSection); 797 begin 798 try 799 CriticalSection.Lock.Acquire; 800 Inc(CriticalSection.FCounter); 801 if CriticalSection.FCounter > 1 then begin 802 CriticalSection.FMicroThreads.Add(Self); 803 FBlockState := tbsCriticalSection; 804 FStatePending := tsBlocked; 805 try 806 CriticalSection.Lock.Release; 807 Yield; 808 finally 809 CriticalSection.Lock.Acquire; 810 end; 811 end; 812 finally 813 CriticalSection.Lock.Release; 814 end; 776 815 end; 777 816 … … 862 901 function TMicroThreadScheduler.Add(MicroThread: TMicroThread): Integer; 863 902 begin 864 Inc(FLastId);865 MicroThread.FScheduler := Self;866 MicroThread.FId := FLastId;867 903 try 868 904 FMicroThreadsLock.Acquire; 905 Inc(FLastId); 906 MicroThread.FScheduler := Self; 907 MicroThread.FId := FLastId; 869 908 Result := FMicroThreads.Add(MicroThread); 870 909 finally … … 873 912 end; 874 913 875 function TMicroThreadScheduler.AddMethod(Method: T MicroThreadMethod): Integer;914 function TMicroThreadScheduler.AddMethod(Method: TProcedureOfObject; WaitForFinish: Boolean): Integer; 876 915 var 877 916 NewMicroThread: TMicroThreadSimple; 878 begin 879 NewMicroThread := TMicroThreadSimple.Create(False); 880 NewMicroThread.Method := Method; 881 NewMicroThread.FScheduler := Self; 882 Result := Add(NewMicroThread); 917 CurrentMT: TMicroThread; 918 begin 919 try 920 NewMicroThread := TMicroThreadSimple.Create(False); 921 NewMicroThread.Method := Method; 922 NewMicroThread.FScheduler := Self; 923 NewMicroThread.FreeOnTerminate := not WaitForFinish; 924 if WaitForFinish then begin 925 CurrentMT := GetCurrentMicroThread; 926 while not ((NewMicroThread.FState = tsBlocked) and 927 (NewMicroThread.FBlockState = tbsTerminated)) do begin 928 try 929 FMicroThreadsLock.Release; 930 if Assigned(CurrentMT) then CurrentMT.MTSleep(1 * OneMillisecond) 931 else begin 932 Sleep(1); 933 Application.ProcessMessages; 934 end; 935 finally 936 FMicroThreadsLock.Acquire; 937 end; 938 end; 939 end; 940 finally 941 if WaitForFinish then NewMicroThread.Free; 942 end; 883 943 end; 884 944 … … 1066 1126 end; 1067 1127 if I < FMicroThreads.Count then begin 1068 if Assigned(Manager.FCurrentMicroThread) then1069 raise Exception.Create(SManagerMicroThreadRunning);1128 // if Assigned(Manager.FCurrentMicroThread) then 1129 // raise EMicroThreadError.Create(SManagerMicroThreadRunning); 1070 1130 Selected := TMicroThread(FMicroThreads[FRoundRobinIndex]); 1071 1131 Selected.FState := tsRunning; … … 1080 1140 procedure TMicroThreadScheduler.ReleaseMicroThread(MicroThread: TMicroThread); 1081 1141 begin 1082 if not Assigned(MicroThread) then1083 raise Exception.Create(SNilThreadReference);1142 // if not Assigned(MicroThread) then 1143 // raise EMicroThreadError.Create(SNilThreadReference); 1084 1144 try 1085 1145 FMicroThreadsLock.Acquire;
Note:
See TracChangeset
for help on using the changeset viewer.