Changeset 149 for MicroThreading/UMicroThreading.pas
- Timestamp:
- Jan 26, 2011, 7:12:08 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
MicroThreading/UMicroThreading.pas
r148 r149 1 (* Not implemented yet 2 - Stack limit checking 3 - 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 *) 8 1 9 unit UMicroThreading; 2 10 … … 7 15 8 16 uses 9 {$IFDEF Windows}Windows,{$ENDIF} 10 {$IFDEF Linux}BaseUnix, UnixUtil, Unix,{$ENDIF} 11 Classes, SysUtils, Contnrs, SyncObjs, DateUtils, Dialogs, Forms; 17 {$IFDEF UNIX}{$IFDEF UseCThreads} 18 cthreads, 19 {$ENDIF}{$ENDIF} 20 Classes, SysUtils, Contnrs, SyncObjs, DateUtils, Dialogs, Forms, UPlatform; 12 21 13 22 const … … 43 52 FManager: TMicroThreadManager; 44 53 FId: Integer; 54 function GetStackUsed: Integer; 45 55 public 46 56 Name: string; … … 69 79 property Scheduler: TMicroThreadScheduler read FScheduler; 70 80 property Manager: TMicroThreadManager read FManager; 81 property StackUsed: Integer read GetStackUsed; 71 82 end; 72 83 … … 80 91 end; 81 92 82 { TMicroThread SchedulerPoolThread }83 84 TMicroThread SchedulerPoolThread = class(TThread)93 { TMicroThreadThread } 94 95 TMicroThreadThread = class(TThread) 85 96 Manager: TMicroThreadManager; 86 97 procedure Execute; override; … … 88 99 const StackSize: SizeUInt = DefaultStackSize); 89 100 destructor Destroy; override; 90 end;91 92 TThreadPool = class(TObjectList)93 101 end; 94 102 … … 123 131 private 124 132 FActive: Boolean; 125 FThreadPool: T ThreadPool;133 FThreadPool: TObjectList; 126 134 FThreadPoolLock: TCriticalSection; 127 135 FThreadPoolSize: Integer; … … 129 137 FLastId: Integer; 130 138 FFrequency: Int64; 131 FTerminate: Boolean;132 139 FTerminated: Boolean; 133 140 FMicroThreads: TObjectList; // TList<TMicroThread> … … 136 143 FState: TMicroThreadSchedulerState; 137 144 function GetMicroThreadCount: Integer; 145 function GetThreadPoolCount: Integer; 138 146 function GetThreadPoolSize: Integer; 139 147 procedure SetActive(const AValue: Boolean); 140 148 procedure SetThreadPoolSize(const AValue: Integer); 141 149 function GetNextMicroThread: TMicroThread; 142 procedure WaitFor;143 150 procedure Start; 144 151 procedure Stop; 145 function ThreadPoolTerminated: Boolean; 152 procedure PoolThreadTerminated(Sender: TObject); 153 procedure UpdateThreadPoolSize; 146 154 public 147 function GetNow: TDateTime;148 155 function Add(MicroThread: TMicroThread): Integer; 149 156 function AddMethod(Method: TMicroThreadEvent): Integer; 150 function GetCPUCoreCount: Integer;151 157 constructor Create; 152 158 destructor Destroy; override; 153 property MicroThreadCount: Integer read GetMicroThreadCount;159 property ThreadPool: TObjectList read FThreadPool; 154 160 property ThreadPoolSize: Integer read GetThreadPoolSize 155 161 write SetThreadPoolSize; 162 property ThreadPoolCount: Integer read GetThreadPoolCount; 156 163 property MicroThreads: TObjectList read FMicroThreads; 157 164 property MicroThreadsLock: TCriticalSection read FMicroThreadsLock; 165 property MicroThreadCount: Integer read GetMicroThreadCount; 158 166 property MainThreadManager: TMicroThreadManager read FMainThreadManager; 159 167 property Active: Boolean read FActive write SetActive; … … 216 224 CurrentTime: TDateTime; 217 225 begin 218 CurrentTime := FScheduler.GetNow;226 CurrentTime := NowPrecise; 219 227 if Assigned(FCurrentMicroThread) then begin 220 228 FCurrentMicroThread.FExecutionEndTime := CurrentTime; … … 268 276 mov edx, [eax].TMicroThread.FStackPointer 269 277 mov esp, edx 270 push ebp 278 push ebp // remember bp on micro thread stack for read back 271 279 mov edx, [eax].TMicroThread.FBasePointer 272 280 mov ebp, edx … … 336 344 end; 337 345 338 { TMicroThread SchedulerPoolThread }339 340 procedure TMicroThread SchedulerPoolThread.Execute;346 { TMicroThreadThread } 347 348 procedure TMicroThreadThread.Execute; 341 349 var 342 350 ExecutedCount: Integer; … … 354 362 end; 355 363 356 constructor TMicroThread SchedulerPoolThread.Create(CreateSuspended: Boolean;364 constructor TMicroThreadThread.Create(CreateSuspended: Boolean; 357 365 const StackSize: SizeUInt); 358 366 begin … … 361 369 end; 362 370 363 destructor TMicroThread SchedulerPoolThread.Destroy;371 destructor TMicroThreadThread.Destroy; 364 372 begin 365 373 Manager.Free; … … 377 385 378 386 { TMicroThread } 387 388 function TMicroThread.GetStackUsed: Integer; 389 begin 390 Result := FStack + FStackSize - FStackPointer; 391 end; 379 392 380 393 procedure TMicroThread.Execute; … … 398 411 procedure TMicroThread.Sleep(Duration: TDateTime); 399 412 begin 400 FWakeUpTime := FScheduler.GetNow+ Duration;413 FWakeUpTime := NowPrecise + Duration; 401 414 FState := tsSleeping; 402 415 Yield; … … 461 474 { TMicroThreadScheduler } 462 475 463 function TMicroThreadScheduler.GetNow: TDateTime;464 var465 {$IFDEF Linux}T: TimeVal;{$ENDIF}466 {$IFDEF Windows}TimerValue: Int64;{$ENDIF}467 begin468 {$IFDEF Windows}469 QueryPerformanceCounter(TimerValue);470 //Result := Int64(TimeStampToMSecs(DateTimeToTimeStamp(Now)) * 1000) // an alternative Win32 timebase471 Result := TimerValue / FFrequency;472 {$ENDIF}473 474 {$IFDEF Linux}475 fpgettimeofday(@t, nil);476 // Build a 64 bit microsecond tick from the seconds and microsecond longints477 Result := t.tv_sec + t.tv_usec / 1000000;478 {$ENDIF}479 480 Result := (Trunc(Now / OneSecond) + Frac(Result)) * OneSecond;481 end;482 483 476 function TMicroThreadScheduler.Add(MicroThread: TMicroThread): Integer; 484 477 begin … … 486 479 MicroThread.FScheduler := Self; 487 480 MicroThread.FId := FLastId; 488 Result := FMicroThreads.Add(MicroThread); 481 try 482 FMicroThreadsLock.Acquire; 483 Result := FMicroThreads.Add(MicroThread); 484 finally 485 FMicroThreadsLock.Release; 486 end; 489 487 end; 490 488 … … 499 497 end; 500 498 501 function TMicroThreadScheduler.GetCPUCoreCount: Integer;502 var503 SystemInfo: _SYSTEM_INFO;504 begin505 GetSystemInfo(SystemInfo);506 Result := SystemInfo.dwNumberOfProcessors;507 end;508 509 499 constructor TMicroThreadScheduler.Create; 510 500 begin … … 512 502 FMicroThreadsLock := TCriticalSection.Create; 513 503 FMicroThreads := TObjectList.Create; 514 FThreadPool := T ThreadPool.Create;504 FThreadPool := TObjectList.Create; 515 505 FThreadPoolLock := TCriticalSection.Create; 516 {$IFDEF Windows}517 QueryPerformanceFrequency(FFrequency);518 {$ENDIF}519 506 FRoundRobinIndex := -1; 520 507 FMainThreadManager := TMicroThreadManager.Create; … … 538 525 begin 539 526 FTerminated := False; 540 FTerminate := False; 541 for I := 0 to FThreadPool.Count - 1 do 542 TMicroThreadSchedulerPoolThread(FThreadPool[I]).Start; 527 UpdateThreadPoolSize; 528 FState := ssRunning; 543 529 repeat 544 530 Executed := FMainThreadManager.Execute(10); 545 531 Application.ProcessMessages; 546 532 if Executed = 0 then Sleep(1); 547 until F Terminate;533 until FState <> ssRunning; 548 534 FTerminated := True; 549 535 end; … … 553 539 I: Integer; 554 540 begin 541 FState := ssTerminating; 555 542 try 556 543 FThreadPoolLock.Acquire; 557 544 for I := 0 to FThreadPool.Count - 1 do begin 558 TMicroThread SchedulerPoolThread(FThreadPool[I]).Terminate;545 TMicroThreadThread(FThreadPool[I]).Terminate; 559 546 end; 560 547 finally 561 548 FThreadPoolLock.Release; 562 549 end; 563 FTerminate := True;564 550 565 551 // Wait for all thread managers to finish … … 568 554 Sleep(1); 569 555 until FTerminated and (ThreadPoolSize = 0); 570 end; 571 572 function TMicroThreadScheduler.ThreadPoolTerminated: Boolean; 573 var 574 I: Integer; 556 FState := ssStopped; 557 end; 558 559 procedure TMicroThreadScheduler.PoolThreadTerminated(Sender: TObject); 575 560 begin 576 561 try 577 562 FThreadPoolLock.Acquire; 578 I := 0; 579 while (I < FThreadPool.Count) and 580 (TMicroThreadSchedulerPoolThread(FThreadPool[I]).Terminated do 563 FThreadPool.Delete(FThreadPool.IndexOf(Sender)); 581 564 finally 582 565 FThreadPoolLock.Release; … … 584 567 end; 585 568 569 procedure TMicroThreadScheduler.UpdateThreadPoolSize; 570 var 571 NewThread: TMicroThreadThread; 572 begin 573 try 574 FThreadPoolLock.Acquire; 575 if FThreadPoolSize > FThreadPool.Count then begin 576 FThreadPool.Capacity := FThreadPoolSize; 577 while FThreadPool.Count < FThreadPoolSize do begin 578 NewThread := TMicroThreadThread.Create(True); 579 NewThread.Manager.FScheduler := Self; 580 NewThread.OnTerminate := PoolThreadTerminated; 581 ThreadPool.Add(NewThread); 582 NewThread.Resume; 583 end; 584 end else 585 ThreadPool.Count := FThreadPoolSize; 586 finally 587 FThreadPoolLock.Release; 588 end; 589 end; 590 586 591 function TMicroThreadScheduler.GetNextMicroThread: TMicroThread; 587 592 var … … 589 594 CurrentTime: TDateTime; 590 595 begin 591 CurrentTime := GetNow;596 CurrentTime := NowPrecise; 592 597 Result := nil; 593 598 try … … 629 634 end; 630 635 636 function TMicroThreadScheduler.GetThreadPoolCount: Integer; 637 begin 638 try 639 FThreadPoolLock.Acquire; 640 Result := FThreadPool.Count; 641 finally 642 FThreadPoolLock.Release; 643 end; 644 end; 645 631 646 function TMicroThreadScheduler.GetThreadPoolSize: Integer; 632 647 begin … … 645 660 var 646 661 I: Integer; 647 NewThread: TMicroThread SchedulerPoolThread;662 NewThread: TMicroThreadThread; 648 663 begin 649 664 FThreadPoolSize := AValue; 650 665 if FState = ssRunning then 651 SetThreadPoolCount666 UpdateThreadPoolSize; 652 667 end; 653 668
Note:
See TracChangeset
for help on using the changeset viewer.