Ignore:
Timestamp:
Jan 28, 2011, 7:33:14 AM (13 years ago)
Author:
george
Message:
  • Modified: Reworked microthread internal states.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • MicroThreading/UMicroThreading.pas

    r154 r155  
    2828  TMicroThreadManager = class;
    2929
    30   TMicroThreadState = (tsWaiting, tsRunning, tsBlocked, tsSuspended,
    31     tsSleeping);
     30  TMicroThreadState = (tsWaiting, tsRunning, tsBlocked, tsSuspended);
     31  TMicroThreadBlockState = (tbsNone, tbsSleeping, tbsWaitFor, tbsTerminating,
     32    tbsTerminated);
    3233
    3334  { TMicroThreadEvent }
     
    6162    FStackSize: Integer;
    6263    FBasePointer: Pointer;
    63     FWakeUpTime: TDateTime;
    64     FTerminated: Boolean;
    6564    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;
    6967    FState: TMicroThreadState;
     68    FStatePending: TMicroThreadState;
    7069    FScheduler: TMicroThreadScheduler;
    7170    FManager: TMicroThreadManager;
    7271    FId: Integer;
    73     FBlockCondition: Boolean;
    7472    procedure CallExecute;
    7573    function GetStackUsed: Integer;
     74    function GetTerminated: Boolean;
    7675    procedure SetScheduler(const AValue: TMicroThreadScheduler);
    7776  public
     
    9695    property Id: Integer read FId;
    9796    property State: TMicroThreadState read FState;
     97    property BlockState: TMicroThreadBlockState read FBlockState;
    9898    property ExecutionTime: TDateTime read FExecutionTime;
    9999    property FreeOnTerminate: Boolean read FFreeOnTerminate
    100100      write FFreeOnTerminate;
    101     property Terminated: Boolean read FTerminated;
     101    property Terminated: Boolean read GetTerminated;
    102102    property Scheduler: TMicroThreadScheduler read FScheduler
    103103      write SetScheduler;
     
    207207const
    208208  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');
    210212
    211213function GetCurrentMicroThread: TMicroThread;
     
    289291begin
    290292  for I := 0 to FMicroThreads.Count - 1 do
    291     TMicroThread(FMicroThreads[I]).FBlockCondition := True;
     293    TMicroThread(FMicroThreads[I]).FStatePending := tsWaiting;
    292294  if not FAutoReset then FSignaled := True;
    293295end;
     
    400402        FCurrentMicroThread.FExecutionTime := FCurrentMicroThread.FExecutionTime +
    401403         (FCurrentMicroThread.FExecutionEndTime - FCurrentMicroThread.FExecutionStartTime);
    402         FCurrentMicroThread.FFinished := True;
     404        FCurrentMicroThread.FState := tsBlocked;
     405        FCurrentMicroThread.FBlockState := tbsTerminated;
    403406        if FCurrentMicroThread.FFreeOnTerminate then begin
    404407          // Microthread is finished, remove it from queue
     
    514517end;
    515518
     519function TMicroThread.GetTerminated: Boolean;
     520begin
     521  Result := (FState = tsBlocked) and (FBlockState = tbsTerminated);
     522end;
     523
    516524procedure TMicroThread.SetScheduler(const AValue: TMicroThreadScheduler);
    517525begin
     
    532540begin
    533541  if GetMicroThreadId <> -1 then
    534   while not FFinished do begin
     542  while not ((FState = tsBlocked) and (FBlockState = tbsTerminated)) do begin
    535543    MTSleep(1);
    536544  end;
     
    539547procedure TMicroThread.MTSleep(Duration: TDateTime);
    540548begin
    541   FWakeUpTime := NowPrecise + Duration;
    542   FState := tsSleeping;
     549  FBlockTime := NowPrecise + Duration;
     550  FBlockState := tbsSleeping;
     551  FStatePending := tsBlocked;
    543552  Yield;
    544553end;
     
    552561    Event.FMicroThreadsLock.Release;
    553562  end;
    554   FBlocked := True;
     563  FBlockTime := NowPrecise + Duration;
     564  FBlockState := tbsWaitFor;
     565  FStatePending := tsBlocked;
    555566  Yield;
    556   repeat
    557     if FState = tsBlocked then MTSleep(1);
    558   until Result <> wrTimeout;
    559567  try
    560568    Event.FMicroThreadsLock.Acquire;
     
    573581  FStackPointer := FBasePointer - SizeOf(Pointer);
    574582  FExecutionTime := 0;
    575   FTerminated := False;
     583  FState := tsWaiting;
     584  FStatePending := tsWaiting;
    576585  if CreateSuspended then begin
    577586    FState := tsSuspended;
    578     FSuspended := True;
    579   end else FSuspended := False;
     587    FStatePending := tsSuspended;
     588  end;
    580589  FFreeOnTerminate := True;
    581590end;
     
    583592procedure TMicroThread.Terminate;
    584593begin
    585   FTerminated := True;
     594  FBlockState := tbsTerminated;
     595  FStatePending := tsBlocked;
    586596end;
    587597
     
    601611procedure TMicroThread.Resume;
    602612begin
    603   FSuspended := False;
    604613  if FState = tsSuspended then
    605     FState := tsWaiting;
     614    FStatePending := tsWaiting;
    606615end;
    607616
    608617procedure TMicroThread.Suspend;
    609618begin
    610   FSuspended := True;
     619  FStatePending := tsSuspended;
    611620  //Yield;
    612621end;
     
    684693procedure TMicroThreadScheduler.Start;
    685694begin
    686   FMainThreadTerminated := False;
    687695  UpdateThreadPoolSize;
    688696  FState := ssRunning;
     
    761769begin
    762770  FMainThreadStarter.Enabled := False;
     771  FMainThreadTerminated := False;
    763772  repeat
    764773    Executed := FMainThreadManager.Execute(1);
     
    782791    if FRoundRobinIndex >= FMicroThreads.Count then
    783792      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
    790797      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;
    800814      end;
     815      // Go to next thread
     816      Inc(I);
     817      Inc(FRoundRobinIndex);
     818      if FRoundRobinIndex >= FMicroThreads.Count then
     819        FRoundRobinIndex := 0;
    801820    end;
    802821    if I < FMicroThreads.Count then begin
    803822      Result := TMicroThread(FMicroThreads[FRoundRobinIndex]);
    804823      Result.FState := tsRunning;
     824      Result.FStatePending := tsWaiting;
    805825    end;
    806826  finally
     
    813833  try
    814834    FMicroThreadsLock.Acquire;
    815     if MicroThread.FState = tsRunning then begin
    816       MicroThread.FState := tsWaiting;
    817     end;
     835    MicroThread.FState := MicroThread.FStatePending;
    818836  finally
    819837    FMicroThreadsLock.Release;
Note: See TracChangeset for help on using the changeset viewer.