Changeset 155 for MicroThreading/UMicroThreading.pas
- Timestamp:
- Jan 28, 2011, 7:33:14 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
MicroThreading/UMicroThreading.pas
r154 r155 28 28 TMicroThreadManager = class; 29 29 30 TMicroThreadState = (tsWaiting, tsRunning, tsBlocked, tsSuspended, 31 tsSleeping); 30 TMicroThreadState = (tsWaiting, tsRunning, tsBlocked, tsSuspended); 31 TMicroThreadBlockState = (tbsNone, tbsSleeping, tbsWaitFor, tbsTerminating, 32 tbsTerminated); 32 33 33 34 { TMicroThreadEvent } … … 61 62 FStackSize: Integer; 62 63 FBasePointer: Pointer; 63 FWakeUpTime: TDateTime;64 FTerminated: Boolean;65 64 FExecuted: Boolean; // At first go through Execute method, then switch context 66 FFinished: Boolean; 67 FSuspended: Boolean; 68 FBlocked: Boolean; 65 FBlockState: TMicroThreadBlockState; 66 FBlockTime: TDateTime; 69 67 FState: TMicroThreadState; 68 FStatePending: TMicroThreadState; 70 69 FScheduler: TMicroThreadScheduler; 71 70 FManager: TMicroThreadManager; 72 71 FId: Integer; 73 FBlockCondition: Boolean;74 72 procedure CallExecute; 75 73 function GetStackUsed: Integer; 74 function GetTerminated: Boolean; 76 75 procedure SetScheduler(const AValue: TMicroThreadScheduler); 77 76 public … … 96 95 property Id: Integer read FId; 97 96 property State: TMicroThreadState read FState; 97 property BlockState: TMicroThreadBlockState read FBlockState; 98 98 property ExecutionTime: TDateTime read FExecutionTime; 99 99 property FreeOnTerminate: Boolean read FFreeOnTerminate 100 100 write FFreeOnTerminate; 101 property Terminated: Boolean read FTerminated;101 property Terminated: Boolean read GetTerminated; 102 102 property Scheduler: TMicroThreadScheduler read FScheduler 103 103 write SetScheduler; … … 207 207 const 208 208 MicroThreadStateText: array[TMicroThreadState] of string = ('Waiting', 209 'Running', 'Blocked', 'Suspended', 'Sleeping'); 209 'Running', 'Blocked', 'Suspended'); 210 MicroThreadBlockStateText: array[TMicroThreadBlockState] of string = ('None', 211 'Sleeping', 'WaitFor', 'Terminating', 'Terminated'); 210 212 211 213 function GetCurrentMicroThread: TMicroThread; … … 289 291 begin 290 292 for I := 0 to FMicroThreads.Count - 1 do 291 TMicroThread(FMicroThreads[I]).F BlockCondition := True;293 TMicroThread(FMicroThreads[I]).FStatePending := tsWaiting; 292 294 if not FAutoReset then FSignaled := True; 293 295 end; … … 400 402 FCurrentMicroThread.FExecutionTime := FCurrentMicroThread.FExecutionTime + 401 403 (FCurrentMicroThread.FExecutionEndTime - FCurrentMicroThread.FExecutionStartTime); 402 FCurrentMicroThread.FFinished := True; 404 FCurrentMicroThread.FState := tsBlocked; 405 FCurrentMicroThread.FBlockState := tbsTerminated; 403 406 if FCurrentMicroThread.FFreeOnTerminate then begin 404 407 // Microthread is finished, remove it from queue … … 514 517 end; 515 518 519 function TMicroThread.GetTerminated: Boolean; 520 begin 521 Result := (FState = tsBlocked) and (FBlockState = tbsTerminated); 522 end; 523 516 524 procedure TMicroThread.SetScheduler(const AValue: TMicroThreadScheduler); 517 525 begin … … 532 540 begin 533 541 if GetMicroThreadId <> -1 then 534 while not FFinisheddo begin542 while not ((FState = tsBlocked) and (FBlockState = tbsTerminated)) do begin 535 543 MTSleep(1); 536 544 end; … … 539 547 procedure TMicroThread.MTSleep(Duration: TDateTime); 540 548 begin 541 FWakeUpTime := NowPrecise + Duration; 542 FState := tsSleeping; 549 FBlockTime := NowPrecise + Duration; 550 FBlockState := tbsSleeping; 551 FStatePending := tsBlocked; 543 552 Yield; 544 553 end; … … 552 561 Event.FMicroThreadsLock.Release; 553 562 end; 554 FBlocked := True; 563 FBlockTime := NowPrecise + Duration; 564 FBlockState := tbsWaitFor; 565 FStatePending := tsBlocked; 555 566 Yield; 556 repeat557 if FState = tsBlocked then MTSleep(1);558 until Result <> wrTimeout;559 567 try 560 568 Event.FMicroThreadsLock.Acquire; … … 573 581 FStackPointer := FBasePointer - SizeOf(Pointer); 574 582 FExecutionTime := 0; 575 FTerminated := False; 583 FState := tsWaiting; 584 FStatePending := tsWaiting; 576 585 if CreateSuspended then begin 577 586 FState := tsSuspended; 578 FS uspended := True;579 end else FSuspended := False;587 FStatePending := tsSuspended; 588 end; 580 589 FFreeOnTerminate := True; 581 590 end; … … 583 592 procedure TMicroThread.Terminate; 584 593 begin 585 FTerminated := True; 594 FBlockState := tbsTerminated; 595 FStatePending := tsBlocked; 586 596 end; 587 597 … … 601 611 procedure TMicroThread.Resume; 602 612 begin 603 FSuspended := False;604 613 if FState = tsSuspended then 605 FState := tsWaiting;614 FStatePending := tsWaiting; 606 615 end; 607 616 608 617 procedure TMicroThread.Suspend; 609 618 begin 610 FS uspended := True;619 FStatePending := tsSuspended; 611 620 //Yield; 612 621 end; … … 684 693 procedure TMicroThreadScheduler.Start; 685 694 begin 686 FMainThreadTerminated := False;687 695 UpdateThreadPoolSize; 688 696 FState := ssRunning; … … 761 769 begin 762 770 FMainThreadStarter.Enabled := False; 771 FMainThreadTerminated := False; 763 772 repeat 764 773 Executed := FMainThreadManager.Execute(1); … … 782 791 if FRoundRobinIndex >= FMicroThreads.Count then 783 792 FRoundRobinIndex := 0; 784 while (I < FMicroThreads.Count) and 785 (TMicroThread(FMicroThreads[FRoundRobinIndex]).FState <> tsWaiting) do begin 786 // WakeUp sleeping threads 787 if (TMicroThread(FMicroThreads[FRoundRobinIndex]).FState = tsSleeping) and 788 (TMicroThread(FMicroThreads[FRoundRobinIndex]).FWakeupTime < CurrentTime) then 789 TMicroThread(FMicroThreads[FRoundRobinIndex]).FState := tsWaiting 793 while (I < FMicroThreads.Count) do 794 with TMicroThread(FMicroThreads[FRoundRobinIndex]) do begin 795 FState := FStatePending; 796 if (FState = tsWaiting) then Break 790 797 else 791 if (TMicroThread(FMicroThreads[FRoundRobinIndex]).FState = tsBlocked) and 792 (TMicroThread(FMicroThreads[FRoundRobinIndex]).FBlockCondition) then 793 TMicroThread(FMicroThreads[FRoundRobinIndex]).FState := tsWaiting 794 else begin 795 // Go to next thread 796 Inc(I); 797 Inc(FRoundRobinIndex); 798 if FRoundRobinIndex >= FMicroThreads.Count then 799 FRoundRobinIndex := 0; 798 if (FState = tsBlocked) then begin 799 // Wakeup sleeping threads 800 if (FBlockState = tbsSleeping) and 801 (FBlockTime < CurrentTime) then begin 802 FState := tsWaiting; 803 FBlockState := tbsNone; 804 Break; 805 end 806 else 807 // Unblock event waiting threads 808 if (FBlockState = tbsWaitFor) and 809 (FBlockTime < CurrentTime) then begin 810 FState := tsWaiting; 811 FBlockState := tbsNone; 812 Break; 813 end; 800 814 end; 815 // Go to next thread 816 Inc(I); 817 Inc(FRoundRobinIndex); 818 if FRoundRobinIndex >= FMicroThreads.Count then 819 FRoundRobinIndex := 0; 801 820 end; 802 821 if I < FMicroThreads.Count then begin 803 822 Result := TMicroThread(FMicroThreads[FRoundRobinIndex]); 804 823 Result.FState := tsRunning; 824 Result.FStatePending := tsWaiting; 805 825 end; 806 826 finally … … 813 833 try 814 834 FMicroThreadsLock.Acquire; 815 if MicroThread.FState = tsRunning then begin 816 MicroThread.FState := tsWaiting; 817 end; 835 MicroThread.FState := MicroThread.FStatePending; 818 836 finally 819 837 FMicroThreadsLock.Release;
Note:
See TracChangeset
for help on using the changeset viewer.