Ignore:
Timestamp:
Jan 31, 2011, 2:16:21 PM (13 years ago)
Author:
george
Message:
  • Added: Running microthread list window.
  • Modified: Main thread is executed by application queued async call.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • MicroThreading/UMicroThreading.pas

    r158 r159  
    1818  cthreads,
    1919  {$ENDIF}{$ENDIF}
    20   Classes, ExtCtrls, SysUtils, Contnrs, SyncObjs, DateUtils, Dialogs, Forms, UPlatform;
     20  Classes, ExtCtrls, SysUtils, Contnrs, SyncObjs, DateUtils, Dialogs, Forms,
     21  UPlatform, UMicroThreadList;
    2122
    2223const
    23   DefaultStackSize = $4000;
     24  DefaultStackSize = $40000;
    2425
    2526type
     
    191192    procedure UpdateThreadPoolSize;
    192193    procedure MainThreadStart(Sender: TObject);
     194    procedure MainThreadTick(Data: PtrInt);
    193195  public
    194196    function Add(MicroThread: TMicroThread): Integer;
    195197    function AddMethod(Method: TMicroThreadMethod): Integer;
    196     procedure Remove(MicroThread: TMicroThread);
     198    function FindCurrentThread: TThread;
     199    procedure Remove(MicroThread: TMicroThread; Free: Boolean = True);
    197200    constructor Create;
    198201    destructor Destroy; override;
     
    210213  end;
    211214
     215  TMicroThreadList = class(TComponent)
     216  private
     217  public
     218    Form: TMicroThreadListForm;
     219    constructor Create(AOwner: TComponent);
     220  end;
     221
     222  TMicroThreadExceptionEvent = procedure(Sender: TObject; E: Exception) of object;
     223
    212224var
    213225  MainScheduler: TMicroThreadScheduler;
     226  ExceptionHandler: TMicroThreadExceptionEvent;
    214227
    215228const
     
    223236function GetCurrentMicroThread: TMicroThread;
    224237procedure MTSleep(Duration: TDateTime);
     238procedure MTSynchronize(Method: TThreadMethod);
    225239function MTWaitForEvent(Event: TMicroThreadEvent; Duration: TDateTime): TWaitResult;
    226240procedure Log(Text: string);
     241procedure Register;
    227242
    228243const
     
    235250//  StaticManager: TMicroThreadManager;
    236251//  StaticMicroThread: TMicroThread;
     252
     253procedure Register;
     254begin
     255  RegisterComponents('MicroThreading', [TMicroThreadList]);
     256end;
    237257
    238258function GetMicroThreadId: Integer;
     
    267287  with MainScheduler do
    268288  try
    269     FThreadPoolLock.Acquire;
     289    FMicroThreadsLock.Acquire;
    270290    if MainThreadID = ThreadID then Result := MainThreadManager.CurrentMicroThread
    271     else begin
    272       I := 0;
    273       while (I < FThreadPool.Count) and (TMicroThreadThread(FThreadPool[I]).ThreadID <> ThreadID) do Inc(I);
    274       if I < FThreadPool.Count then Result := TMicroThreadThread(FThreadPool[I]).Manager.CurrentMicroThread
    275         else Result := nil;
    276     end;
    277   finally
    278     FThreadPoolLock.Release;
     291      else Result := TMicroThreadThread(MainScheduler.FindCurrentThread).Manager.CurrentMicroThread;
     292  finally
     293    FMicroThreadsLock.Release;
    279294  end;
    280295end;
     
    289304end;
    290305
     306procedure MTSynchronize(Method: TThreadMethod);
     307var
     308  Thread: TThread;
     309begin
     310  if GetCurrentThreadId <> MainThreadID then begin
     311    Thread := MainScheduler.FindCurrentThread;
     312    if Assigned(Thread) then TThread.Synchronize(Thread, Method)
     313      else raise Exception.Create('Can''t determine thread for id ' + IntToStr(GetCurrentThreadId));
     314  end else Method;
     315end;
     316
    291317function MTWaitForEvent(Event: TMicroThreadEvent; Duration: TDateTime): TWaitResult;
    292318var
     
    294320begin
    295321  MT := GetCurrentMicroThread;
    296   if Assigned(MT) then Result := MT.WaitForEvent(Event, Duration);
     322  if Assigned(MT) then Result := MT.WaitForEvent(Event, Duration)
     323    else raise Exception.Create('Not in thread');
    297324//    else Result := Event.WaitFor(Trunc(Duration / OneMillisecond));
    298325end;
     
    316343  end;
    317344end;
     345
     346{ TMicroThreadList }
     347
     348constructor TMicroThreadList.Create(AOwner: TComponent);
     349begin
     350  inherited;
     351  Form := TMicroThreadListForm.Create(Self);
     352end;
     353
     354
    318355
    319356{ TMicroThreadMethod }
     
    360397destructor TMicroThreadEvent.Destroy;
    361398begin
    362   MainScheduler.FEvents.Delete(MainScheduler.FEvents.IndexOf(Self));
     399  try
     400    MainScheduler.FEvents.OwnsObjects := False;
     401    MainScheduler.FEvents.Delete(MainScheduler.FEvents.IndexOf(Self));
     402  finally
     403    MainScheduler.FEvents.OwnsObjects := True;
     404  end;
    363405  FMicroThreadsLock.Free;
    364406  FMicroThreads.Free;
     
    441483          // but virtual methods can be called only statically
    442484          // Then static method CallExecute is calling virtual method Execute
    443           call TMicroThread.CallExecute
     485            call TMicroThread.CallExecute
    444486
    445487          // Restore manager stack
     
    522564    until Terminated;
    523565  except
    524     on E: Exception do ;
    525       //ExceptionHandler(E);
     566    on E: Exception do
     567      if Assigned(ExceptionHandler) then ExceptionHandler(Self, E);
    526568  end;
    527569end;
     
    549591end;
    550592
    551 
    552593{ TMicroThread }
    553594
    554595procedure TMicroThread.CallExecute;
    555596begin
    556   Execute;
     597  try
     598    Execute;
     599  except
     600    on E: Exception do
     601      ExceptionHandler(Self, E);
     602  end;
    557603  asm
    558604    mov ecx, Self
     
    631677  end;
    632678  Yield;
     679  if FBlockTime < NowPrecise then
     680    Result := wrTimeout else Result := wrSignaled;
     681
    633682  try
    634683    Event.FMicroThreadsLock.Acquire;
     
    669718destructor TMicroThread.Destroy;
    670719begin
     720  MainScheduler.Remove(Self, False);
    671721  //Terminate;
    672722  //WaitFor;
     
    718768end;
    719769
    720 procedure TMicroThreadScheduler.Remove(MicroThread: TMicroThread);
     770function TMicroThreadScheduler.FindCurrentThread: TThread;
     771var
     772  I: Integer;
     773begin
     774  try
     775    FThreadPoolLock.Acquire;
     776    I := 0;
     777    while (I < FThreadPool.Count) and (TMicroThreadThread(FThreadPool[I]).ThreadID <> ThreadID) do Inc(I);
     778    if I < FThreadPool.Count then Result := TMicroThreadThread(FThreadPool[I])
     779      else Result := nil;
     780  finally
     781    FThreadPoolLock.Release;
     782  end;
     783end;
     784
     785procedure TMicroThreadScheduler.Remove(MicroThread: TMicroThread;
     786  Free: Boolean = True);
    721787begin
    722788  try
    723789    FMicroThreadsLock.Acquire;
     790    if not Free then FMicroThreads.OwnsObjects := False;
    724791    FMicroThreads.Remove(MicroThread);
     792    FMicroThreads.OwnsObjects := True;
    725793  finally
    726794    FMicroThreadsLock.Release;
     
    824892
    825893procedure TMicroThreadScheduler.MainThreadStart(Sender: TObject);
    826 var
    827   Executed: Integer;
    828894begin
    829895  FMainThreadStarter.Enabled := False;
    830896  FMainThreadTerminated := False;
    831   repeat
    832     Executed := FMainThreadManager.Execute(1);
    833     Application.ProcessMessages;
    834     if Executed = 0 then Sleep(1);
    835   until (FState <> ssRunning) or (not FUseMainThread);
    836   FMainThreadTerminated := True;
     897  Application.QueueAsyncCall(MainThreadTick, 0);
     898end;
     899
     900procedure TMicroThreadScheduler.MainThreadTick(Data: PtrInt);
     901var
     902  Executed: Integer;
     903begin
     904  Executed := FMainThreadManager.Execute(1);
     905  if Executed = 0 then Sleep(1);
     906  // If not terminated then queue next tick else terminate
     907  if (FState = ssRunning) and FUseMainThread then
     908    Application.QueueAsyncCall(MainThreadTick, 0)
     909    else FMainThreadTerminated := True;
    837910end;
    838911
Note: See TracChangeset for help on using the changeset viewer.