Ignore:
Timestamp:
Feb 7, 2011, 1:04:27 PM (14 years ago)
Author:
george
Message:
  • Add: MicroThread critical section.
  • Add: Thread list to microthread list window.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • MicroThreading/UMicroThreading.pas

    r161 r162  
    1 (* Not implemented yet
     1// Date: 2010-02-07
     2
     3(*
     4Not implemented yet
    25- Stack limit checking
    36- measurement of cpu usage by micro threads
    4 - microthread critical sections (no low level cpu blocking)
    5 - wait for single and multiple objects
    6 - micro thread priorty
     7- wait for multiple objects
     8- micro thread priority
    79*)
    810
     
    3133  SCantDetermineThreadID = 'Can''t determine thread for id %d';
    3234  SNotInThread = 'Not in thread';
     35  SReleaseNotAcquiredLock = 'Release not acquired lock';
    3336
    3437
     
    4144  TMicroThreadBlockState = (tbsNone, tbsSleeping, tbsWaitFor, tbsTerminating,
    4245    tbsTerminated);
     46
     47  { TMicroThreadCriticalSection }
     48
     49  TMicroThreadCriticalSection = class
     50    Lock: TCriticalSection;
     51    Counter: Integer;
     52    procedure Acquire;
     53    procedure Release;
     54    constructor Create;
     55    destructor Destroy; override;
     56  end;
    4357
    4458  { TMicroThreadEvent }
     
    5367    procedure SetEvent;
    5468    procedure ResetEvent;
    55     procedure WaitFor(Duration: TDateTime);
     69    function WaitFor(Duration: TDateTime): TWaitResult;
    5670    constructor Create;
    5771    destructor Destroy; override;
     
    7084    FExecutionCount: Integer;
    7185    FStack: Pointer;
    72     FStackPointer: Pointer;
     86    FStackPointer: Pointer; // Register SP
    7387    FStackSize: Integer;
    74     FBasePointer: Pointer;
     88    FBasePointer: Pointer; // Register BP
    7589    FExceptObjectStack: PExceptObject;
    7690    FExceptAddrStack: PExceptAddr;
     
    160174    FThread: TMicroThreadThread;
    161175    FId: Integer;
     176    FLoopDuration: TDateTime;
     177    FLoopStart: TDateTime;
    162178    procedure SetCurrentMicroThread(const AValue: TMicroThread);
    163179    function Execute(Count: Integer): Integer;
     
    170186    destructor Destroy; override;
    171187    property Scheduler: TMicroThreadScheduler read FScheduler;
     188    property LoopDuration: TDateTime read FLoopDuration;
     189    function GetCurrentMicroThreadId: Integer;
    172190  end;
    173191
     
    206224    procedure MainThreadTick(Data: PtrInt);
    207225  public
     226    BurstCount: Integer;
    208227    function Add(MicroThread: TMicroThread): Integer;
    209228    function AddMethod(Method: TMicroThreadMethod): Integer;
     
    343362end;
    344363
     364{ TMicroThreadCriticalSection }
     365
     366procedure TMicroThreadCriticalSection.Acquire;
     367begin
     368  try
     369    Lock.Acquire;
     370    while Counter > 0 do begin
     371      try
     372        Lock.Release;
     373        MTSleep(1 * OneMillisecond);
     374      finally
     375        Lock.Acquire;
     376      end;
     377    end;
     378    Inc(Counter);
     379  finally
     380    Lock.Release;
     381  end;
     382end;
     383
     384procedure TMicroThreadCriticalSection.Release;
     385begin
     386  try
     387    Lock.Acquire;
     388    if Counter > 0 then Dec(Counter)
     389      else raise Exception.Create(SReleaseNotAcquiredLock);
     390  finally
     391    Lock.Release;
     392  end;
     393end;
     394
     395constructor TMicroThreadCriticalSection.Create;
     396begin
     397  Lock := TCriticalSection.Create;
     398end;
     399
     400destructor TMicroThreadCriticalSection.Destroy;
     401begin
     402  Acquire;
     403  Lock.Free;
     404  inherited Destroy;
     405end;
     406
    345407{ TMicroThreadList }
    346408
     
    363425    for I := 0 to FMicroThreads.Count - 1 do
    364426    with TMicroThread(FMicroThreads[I]) do begin
    365       if (FState = tsBlocked) and (FBlockState = tbsWaitFor) then
     427      if (FState = tsBlocked) and (FBlockState = tbsWaitFor) then begin
    366428        FState := tsWaiting;
     429        FBlockTime := 0; // Set signaled state using block time variable
     430      end;
    367431    end;
    368432    if not FAutoReset then FSignaled := True;
     
    377441end;
    378442
    379 procedure TMicroThreadEvent.WaitFor(Duration: TDateTime);
     443function TMicroThreadEvent.WaitFor(Duration: TDateTime): TWaitResult;
    380444var
    381445  MT: TMicroThread;
    382446begin
    383447  MT := GetCurrentMicroThread;
    384   if Assigned(MT) then MT.WaitForEvent(Self, Duration);
     448  if Assigned(MT) then Result := MT.WaitForEvent(Self, Duration)
     449    else Result := wrSignaled;
    385450end;
    386451
     
    422487function TMicroThreadManager.Execute(Count: Integer): Integer;
    423488begin
     489  FLoopStart := NowPrecise;
    424490  FStack := StackBottom;
    425491  FStackSize := StackBottom + StackLength;
     
    428494  Yield;
    429495  Result := FExecutedCount;
     496  FLoopDuration := NowPrecise - FLoopStart;
    430497end;
    431498
     
    489556          mov ebp, ebx
    490557          // We want to call virtual method Execute
    491           // but virtual methods can be called only statically
     558          // but methods can be called only statically from assembler
    492559          // Then static method CallExecute is calling virtual method Execute
    493560          call TMicroThread.CallExecute
     
    515582            FMicroThreadsLock.Acquire;
    516583            FMicroThreads.Delete(FMicroThreads.IndexOf(FCurrentMicroThread));
    517             FCurrentMicroThread.Manager := nil;
     584            FCurrentMicroThread := nil;
    518585          finally
    519586            FMicroThreadsLock.Release;
     
    562629end;
    563630
     631function TMicroThreadManager.GetCurrentMicroThreadId: Integer;
     632begin
     633  try
     634    FScheduler.FMicroThreadsLock.Acquire;
     635    if Assigned(FCurrentMicroThread) then
     636      Result := FCurrentMicroThread.Id
     637      else Result := 0;
     638  finally
     639    FScheduler.FMicroThreadsLock.Release;
     640  end;
     641end;
     642
    564643{ TMicroThreadThread }
    565644
     
    571650    repeat
    572651      State := ttsRunning;
    573       ExecutedCount := Manager.Execute(10);
     652      ExecutedCount := Manager.Execute(MainScheduler.BurstCount);
    574653      State := ttsReady;
    575654      if ExecutedCount = 0 then Sleep(1);
     
    691770  end;
    692771  Yield;
    693   if FBlockTime < NowPrecise then
    694     Result := wrTimeout else Result := wrSignaled;
     772  if (FBlockTime <> 0) and (FBlockTime < NowPrecise) then Result := wrTimeout
     773    else Result := wrSignaled;
    695774
    696775  try
     
    811890  FMainThreadManager.FScheduler := Self;
    812891  UseMainThread := False;
     892  BurstCount := 100;
    813893end;
    814894
     
    900980var
    901981  Executed: Integer;
     982  StartTime: TDateTime;
     983  Duration: TDateTime;
    902984begin
    903985//  try
    904     Executed := FMainThreadManager.Execute(1);
    905     if Executed = 0 then Sleep(1);
     986    Duration := 100 * OneMillisecond;
     987    StartTime := NowPrecise;
     988    Executed := -1;
     989    while (Executed <> 0) and ((NowPrecise - StartTime) < Duration) do begin
     990      Executed := FMainThreadManager.Execute(BurstCount);
     991    end;
     992    //if Executed = 0 then Sleep(1);
    906993    // If not terminated then queue next tick else terminate
    907994    if (FState = ssRunning) and FUseMainThread then
Note: See TracChangeset for help on using the changeset viewer.