Ignore:
Timestamp:
Feb 1, 2011, 10:06:01 AM (14 years ago)
Author:
george
Message:
  • Added: Unit UThreadEx which introduce class TThreadEx with support for method CurrentThread. Unit automatic mantain runtime thread list.
  • Added: Testing of exceptions raised inside microthread in demo application.
Location:
MicroThreading
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • MicroThreading

    • Property svn:ignore
      •  

        old new  
        11lib
         2backup
  • MicroThreading/UMicroThreading.pas

    r159 r160  
    1919  {$ENDIF}{$ENDIF}
    2020  Classes, ExtCtrls, SysUtils, Contnrs, SyncObjs, DateUtils, Dialogs, Forms,
    21   UPlatform, UMicroThreadList;
     21  UPlatform, UMicroThreadList, UThreadEx;
    2222
    2323const
    24   DefaultStackSize = $40000;
     24  DefaultStackSize = $4000;
     25
     26resourcestring
     27  SStackOverflow = 'Microthread %d stack error. Pointer %s , range < %s ; %s >';
     28  SNilThreadReference = 'Can''t release nil thread.';
     29  SManagerMicroThreadRunning = 'Manager already have running microthread';
    2530
    2631type
     
    124129  { TMicroThreadThread }
    125130
    126   TMicroThreadThread = class(TThread)
     131  TMicroThreadThread = class(TThreadEx)
    127132    Manager: TMicroThreadManager;
    128133    State: TMicroThreadThreadState;
     
    171176    FRoundRobinIndex: Integer;
    172177    FLastId: Integer;
    173     FFrequency: Int64;
    174178    FMainThreadTerminated: Boolean;
    175179    FMicroThreads: TObjectList; // TList<TMicroThread>
     
    196200    function Add(MicroThread: TMicroThread): Integer;
    197201    function AddMethod(Method: TMicroThreadMethod): Integer;
    198     function FindCurrentThread: TThread;
    199202    procedure Remove(MicroThread: TMicroThread; Free: Boolean = True);
    200203    constructor Create;
     
    217220  public
    218221    Form: TMicroThreadListForm;
    219     constructor Create(AOwner: TComponent);
     222    constructor Create(AOwner: TComponent); override;
    220223  end;
    221224
     
    258261function GetMicroThreadId: Integer;
    259262var
    260   I: Integer;
    261   CurrentStack: Pointer;
    262 begin
    263   asm
    264     mov CurrentStack, sp
    265   end;
    266   with MainScheduler do begin
    267     try
    268       FMicroThreadsLock.Acquire;
    269       I := 0;
    270       while (I < FMicroThreads.Count) and
    271         not ((CurrentStack >= TMicroThread(FMicroThreads[I]).FStack) and
    272         (CurrentStack <= (TMicroThread(FMicroThreads[I]).FStack +
    273         TMicroThread(FMicroThreads[I]).FStackSize))) do Inc(I);
    274       if I < FMicroThreads.Count then begin
    275         Result := TMicroThread(FMicroThreads[I]).FId;
    276       end else Result := -1;
    277     finally
    278       FMicroThreadsLock.Release;
    279     end;
    280   end;
     263  MT: TMicroThread;
     264begin
     265  MT := GetCurrentMicroThread;
     266  if Assigned(MT) then Result := MT.Id else Result := -1;
    281267end;
    282268
    283269function GetCurrentMicroThread: TMicroThread;
    284270var
    285   I: Integer;
     271  Thread: TThread;
    286272begin
    287273  with MainScheduler do
     
    289275    FMicroThreadsLock.Acquire;
    290276    if MainThreadID = ThreadID then Result := MainThreadManager.CurrentMicroThread
    291       else Result := TMicroThreadThread(MainScheduler.FindCurrentThread).Manager.CurrentMicroThread;
     277      else begin
     278        Thread := TThreadEx.CurrentThread;
     279        if Assigned(Thread) then
     280          Result := TMicroThreadThread(Thread).Manager.CurrentMicroThread
     281          else Result := nil;
     282      end;
    292283  finally
    293284    FMicroThreadsLock.Release;
     
    309300begin
    310301  if GetCurrentThreadId <> MainThreadID then begin
    311     Thread := MainScheduler.FindCurrentThread;
     302    Thread := TThreadEx.CurrentThread;
    312303    if Assigned(Thread) then TThread.Synchronize(Thread, Method)
    313304      else raise Exception.Create('Can''t determine thread for id ' + IntToStr(GetCurrentThreadId));
     
    483474          // but virtual methods can be called only statically
    484475          // Then static method CallExecute is calling virtual method Execute
    485             call TMicroThread.CallExecute
     476          call TMicroThread.CallExecute
    486477
    487478          // Restore manager stack
     
    555546  ExecutedCount: Integer;
    556547begin
    557   inherited Execute;
    558548  try
    559549    repeat
     
    599589  except
    600590    on E: Exception do
    601       ExceptionHandler(Self, E);
     591      if Assigned(ExceptionHandler) then ExceptionHandler(Self, E);
    602592  end;
    603593  asm
     
    632622begin
    633623  if not ((FStackPointer > FStack) and (FStackPointer < (FStack + FStackSize)))
    634     then raise EStackOverflow.Create(Format('Microthread %d stack error', [FId]));
     624    then raise EStackOverflow.Create(Format(SStackOverflow,
     625      [FId, IntToHex(Integer(FStackPointer), 8), IntToHex(Integer(FStack), 8),
     626      IntToHex(Integer(FStack + FStackSize), 8)]));
    635627end;
    636628
     
    766758  NewMicroThread.FScheduler := Self;
    767759  Result := Add(NewMicroThread);
    768 end;
    769 
    770 function TMicroThreadScheduler.FindCurrentThread: TThread;
    771 var
    772   I: Integer;
    773 begin
    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;
    783760end;
    784761
     
    951928    if I < FMicroThreads.Count then begin
    952929      if Assigned(Manager.FCurrentMicroThread) then
    953         raise Exception.Create('Manager have already have running microthread');
     930        raise Exception.Create(SManagerMicroThreadRunning);
    954931      Selected := TMicroThread(FMicroThreads[FRoundRobinIndex]);
    955932      Selected.FState := tsRunning;
     
    965942begin
    966943  if not Assigned(MicroThread) then
    967     raise Exception.Create('Can''t release nil thread.');
     944    raise Exception.Create(SNilThreadReference);
    968945  try
    969946    FMicroThreadsLock.Acquire;
Note: See TracChangeset for help on using the changeset viewer.