mormot.core.threads.pas unit
mormot.core.threads.pas unit
Purpose: Framework Core Multi-Threading Support
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md
目的:框架核心多线程支持
- 本单元是开源Synopse mORMot框架2的一部分,根据MPL/GPL/LGPL三重许可进行许可-参见LICENSE.md
1.1. Units used in the mormot.core.threads unit (在mormot.core.threads单元中使用的单元)
Unit Name | Description | |
---|---|---|
mormot.core.base | Framework Core Shared Types and RTL-like Functions | 框架核心共享类型和类似RTL的函数 |
mormot.core.buffers | Framework Core Low-Level Memory Buffer Process | 框架核心低级内存缓冲区处理 |
mormot.core.data | Framework Core Low-Level Data Processing Functions | 框架核心低级数据处理函数 |
mormot.core.json | Framework Core Low-Level JSON Processing | 框架核心低级JSON处理 |
mormot.core.log | Framework Core Logging | 框架核心日志记录 |
mormot.core.os | Framework Core Low-Level Wrappers to the Operating-System API | 框架核心对操作系统API的低级包装器 |
mormot.core.perf | Framework Core Performance and Monitoring Classes | 框架核心性能和监视类 |
mormot.core.rtti | Framework Core Low-Level Cross-Compiler RTTI Definitions | 框架核心低级跨编译器RTTI定义 |
mormot.core.text | Framework Core Low-Level Text Processing | 框架核心低级文本处理 |
mormot.core.unicode | Framework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion | 框架核心低级Unicode UTF-8 UTF-16 Ansi转换 |
mormot.core.variants | Framework Core Low-Level Variants / TDocVariant process | 框架核心低级变量/TDocVariant处理 |
1.2. mormot.core.threads class hierarchy
TSynThread
TSynThreadPoolWorkThread
TNotifiedThreadTLoggedThread
TLoggedWorkThreadTThreadAbstract
TSynBackgroundThreadAbstract
TSynBackgroundThreadProcess
TSynBackgroundTimer
TSynBackgroundThreadMethodAbstract
TSynParallelProcessThread
TSynBackgroundThreadProcedure
TSynBackgroundThreadMethod
TSynBackgroundThreadEventTThread
TSynPersistentStoreTSynQueue
TSynPersistentLockTSynParallelProcess
TSynPersistent
TBlockingProcessPool
TBlockingProcess
TBlockingProcessPoolItem
TSynEventTObject
TSynThreadPool
TPendingTaskList
TInterfacedObjectWithCustomCreate
TLockedDocVariantIInterface
ILockedDocVariant
ESynException
ESynThread
mormot.core.threads class hierarchy
1.3. Objects implemented in the mormot.core.threads unit (mormot.core.threads 单元中实现的对象)
Objects | Description | |
---|---|---|
ESynThread | Exception class raised by this unit | 由本单元引发的异常类 |
ILockedDocVariant | Ref-counted interface for thread-safe access to a TDocVariant document | 用于线程安全访问TDocVariant文档的引用计数接口 |
TBlockingProcess | A semaphore used to wait for some process to be finished | 一个计数信号量,用于等待某个进程完成 |
TBlockingProcessPool | Manage a pool of TBlockingProcessPoolItem instances | 管理一组TBlockingProcessPoolItem实例 |
TBlockingProcessPoolItem | A semaphore used in the TBlockingProcessPool | 在TBlockingProcessPool中使用的计数信号量 |
TLockedDocVariant | Allows thread-safe access to a TDocVariant document | 允许线程安全地访问TDocVariant文档 |
TLoggedThread | Abstract class to implement a thread with logging notifications | 实现带有日志通知的线程的抽象类 |
TLoggedWorkThread | A class able to run some process in a background thread | 能够在后台线程中运行某些进程的类 |
TNotifiedThread | Abstract class to implement a thread with start/stop notifications | 实现带有启动/停止通知的线程的抽象类 |
TPendingTaskList | Thread-safe list of tasks, stored as RawByteString, with a timestamp | 线程安全的任务列表,以RawByteString形式存储,带有时间戳 |
TPendingTaskListItem | Internal item definition, used by TPendingTaskList storage | TPendingTaskList存储的内部项目定义 |
TSynBackgroundThreadAbstract | Abstract TThread with its own execution content | 带有自己的执行内容的TThreadAbstract |
TSynBackgroundThreadEvent | Allow background thread process of a method callback | 允许在后台线程中处理方法回调 |
TSynBackgroundThreadMethod | Allow background thread process of a variable TThreadMethod callback | 允许在后台线程中处理可变TThreadMethod回调 |
TSynBackgroundThreadMethodAbstract | Abstract TThread able to run a method in its own execution content | 能够在自己的执行内容中运行方法的抽象TThread |
TSynBackgroundThreadProcedure | Allow background thread process of a procedure callback | 允许在后台线程中处理过程回调 |
TSynBackgroundThreadProcess | TThread able to run a method at a given periodic pace | 能够在给定周期速率下运行方法的TThread |
TSynBackgroundTimer | TThread able to run one or several tasks at a periodic pace in a background thread | 能够在后台线程中以周期速率运行一个或多个任务的TThread |
TSynBackgroundTimerTask | Used by TSynBackgroundTimer internal registration list | 用于TSynBackgroundTimer内部注册列表 |
TSynParallelProcess | Allow parallel execution of an index-based process in a thread pool | 允许在线程池中并行执行基于索引的进程 |
TSynParallelProcessThread | Thread executing process for TSynParallelProcess | 为TSynParallelProcess执行进程的线程 |
TSynQueue | Thread-safe FIFO (First-In-First-Out) in-order queue of records | 线程安全的FIFO(先入先出)有序记录队列 |
TSynThread | A simple TThread with a "Terminate" event run in the thread context | 一个简单的TThread,带有在线程上下文中运行的"Terminate"事件 |
TSynThreadPool | A simple Thread Pool, used e.g. for fast handling HTTP/1.0 requests | 一个简单的线程池,例如用于快速处理HTTP/1.0请求 |
TSynThreadPoolWorkThread | Defines the work threads used by TSynThreadPool | 定义TSynThreadPool使用的工作线程 |
TThreadAbstract | Abstract parent of all TThread inherited classes | 所有TThread继承类的抽象父类 |
1.3.1. ESynThread
ESynThread = class(ESynException)
本单元引发的异常类
1.3.2. TSynQueue
TSynQueue = class(TSynPersistentStore)
*线程安全的FIFO(先入先出)记录有序队列
- 内部使用
TDynArray
存储,具有滑动算法,比FPC或Delphi的TQueue或简单的TDynArray.Add
/Delete更高效 - 如果需要,支持
TSynPersistentStore
二进制持久化 - 该结构在设计上也是线程安全的*
constructor Create(aTypeInfo: PRttiInfo; const aName: RawUtf8 = ''); reintroduce; virtual;
*初始化队列存储
destructor Destroy; override;
*销毁存储
- 将释放所有内部存储的值,并调用
WaitPopFinalize
*
function Capacity: integer;
*返回当前在内存中预留的槽位数
- 队列具有优化的自动调整大小算法,可以使用此方法返回其当前
capacity
- 此方法不是线程安全的,因此返回的值仅具有指示性*
function Count: integer;
*返回当前存储在此队列中的项数
- 此方法不是线程安全的,因此返回的值要么具有指示性,要么应使用显式的安全锁定/解锁
- 如果要检查队列是否为空,请调用
Pending
*
function Peek(out aValue): boolean;
*从队列中按FIFO(先入先出)方式查找一个项
function Pending: boolean;
*如果队列中有一些当前pending
的项,则返回true
function Pop(out aValue): boolean;
*从队列中按FIFO(先入先出)方式提取一个项
function PopEquals(aAnother: pointer; aCompare: TDynArraySortCompare; out aValue): boolean;
*从队列中按FIFO(先入先出)方式提取一个匹配的项
- 当前
pending
项与aAnother值进行比较*
function WaitPeekLocked(aTimeoutMS: integer; const aWhenIdle: TThreadMethod): pointer;
*等待从队列中按FIFO(先入先出)方式查找一个项
- 在aTimeoutMS时间内返回一个指向
pending
项的指针 - 保持Safe.ReadWriteLock,因此调用者可以检查其内容,然后如果它是预期的项,则调用
Pop
(),并最终调用Safe.ReadWriteUnlock - 如果在时间内没有将任何内容推入队列,则返回nil
- 此方法是线程安全的,但仅在需要时锁定实例*
function WaitPop(aTimeoutMS: integer; const aWhenIdle: TThreadMethod; out aValue; aCompared: pointer = nil; aCompare: TDynArraySortCompare = nil): boolean;
*等待并从队列中按FIFO(先入先出)方式提取一个项
- 如果在指定的aTimeoutMS时间内aValue已被填充了一个
pending
项,则返回true - 如果在时间内没有将任何内容推入队列,或者已调用
WaitPopFinalize
,则返回false - aWhenIdle可以被分配,例如给VCL/LCL Application.ProcessMessages
- 可以在返回之前可选地比较
pending
项(例如,当多个线程将项放入队列时可以使用) - 此方法是线程安全的,但仅在需要时锁定实例*
procedure Clear;
*删除当前存储在此队列中的所有项,并清空其capacity
- 此方法是线程安全的,因为它将锁定实例*
procedure Push(const aValue);
*将一个项存储
到队列中
- 此方法是线程安全的,因为它将锁定实例*
procedure Save(out aDynArrayValues; aDynArray: PDynArray = nil); overload;
*使用存储的队列项初始化一个动态数组
procedure WaitPopFinalize(aTimeoutMS: integer = 100);
*确保任何pending
或未来的WaitPop
()方法立即返回false
- 总是由
Destroy
析构函数调用 - 也可以从UI的OnClose事件中调用,以避免任何锁定
- 此方法是线程安全的,但仅在需要时锁定实例*
1.3.3. TPendingTaskListItem
TPendingTaskListItem = packed record
内部项目定义,由TPendingTaskList
存储使用
Task: RawByteString;
相关联的task
,以原始二进制形式存储
Timestamp: Int64;
当TPendingTaskList.GetTimestamp达到此值时,应执行task
1.3.4. TPendingTaskList
TPendingTaskList = class(TObject)
*线程安全的任务列表,以RawByteString
形式存储,并带有时间戳
- 你可以向内部列表添加任务,以在给定延迟后执行,使用类似于post/peek的算法
- 执行延迟预计不准确,但根据每次NextPendingTask调用和GetTimestamp解析度进行最佳猜测*
constructor Create; reintroduce;
默认返回GetTickCount64
来初始化列表内存和资源
function NextPendingTask: RawByteString; virtual;
*检索下一个待处理task
- 如果当前没有计划中的
task
,则返回'' - 返回与指定延迟相对应的下一个堆栈*
procedure AddTask(aMilliSecondsDelayFromNow: integer; const aTask: RawByteString); virtual;
procedure AddTasks(const aMilliSecondsDelays: array of integer; const aTasks: array of RawByteString);
*指定任务之间的毫秒延迟后Append
多个任务
- 第一个提供的延迟将从当前时间开始计算,然后它将指定等待下一个提供
task
需要多长时间——也就是说,aMilliSecondsDelays不是绝对延迟*
procedure Clear; virtual;
清除所有待处理任务
property Count: integer read GetCount;
当前定义了多少个待处理任务
property Task: TPendingTaskListItemDynArray read fTask;
*直接低级访问内部task
列表
- 警告:此动态数组的长度是列表容量:请使用
Count
属性来检索存储的确切项数 - 使用try ... finally Safe.Unlock块中的Safe.Lock/TryLock进行线程安全访问此数组
- 项目按递增的
Timestamp
存储,即第一个项目是NextPendingTask
方法将返回的下一个项目*
property Timestamp: Int64 read GetTimestamp;
*访问内部TPendingTaskListItem.Timestamp
存储的值
- 对应当前时间
- 默认实现是返回
GetTickCount64
,在Windows下典型分辨率为16毫秒*
1.3.5. ILockedDocVariant
ILockedDocVariant = interface(IInterface)
*用于线程安全访问TDocVariant
文档的引用计数接口
- 例如,由
TLockedDocVariant
实现,用于IoC/DI解析 - 快速且安全地存储任何类似JSON的对象,作为属性/值对,或类似JSON的数组,作为值*
function AddExistingProp(const Name: RawUtf8; var Obj: variant): boolean;
*将现有属性value
添加到给定的TDocVariant
文档对象
- 如果Name存在,则返回TRUE并将Name/
Value
对添加到Obj - 如果存储的文档中不存在Name,则返回FALSE
- 此方法在查找Name期间会使用
lock
,但无论是否返回FALSE,总是会释放lock
(参见AddExistingPropOrLock
)*
function AddExistingPropOrLock(const Name: RawUtf8; var Obj: variant): boolean;
*将现有属性value
添加到给定的TDocVariant
文档对象
- 如果Name存在,则返回TRUE并将Name/
Value
对添加到Obj,使用内部lock
确保线程安全 - 如果存储的文档中不存在Name,则返回FALSE并锁定内部存储:调用者最终应通过
AddNewPropAndUnlock
()释放lock
- 可以这样使用,以实现线程安全的缓存:
if not cache.AddExistingPropOrLock('Articles',Scope) then
cache.AddNewPropAndUnlock('Articles',GetArticlesFromDB,Scope);
这里GetArticlesFromDB会在主要lock
内部执行
function Copy: variant;
对内部TDocVariant
文档对象或数组进行线程安全的复制
function Exists(const Name: RawUtf8; out Value: Variant): boolean;
*按名称检查和返回一个给定的属性
- 如果找到Name,则返回TRUE并将与提供的Name相关联的
value
填充到Value
中,使用内部lock
确保线程安全 - 如果未找到Name,则返回FALSE并释放内部
lock
:如果你想要添加缺失的value
,请使用ExistsOrLock
()*
function ExistsOrLock(const Name: RawUtf8; out Value: Variant): boolean;
*按名称检查和返回一个给定的属性
- 如果找到Name,则返回TRUE并将与提供的Name相关联的
value
填充到Value
中,使用内部lock
确保线程安全 - 如果Name不存在,则返回FALSE并设置内部
lock
:调用者随后应通过ReplaceAndUnlock
()释放lock
*
function Lock: TAutoLocker;
对关联的线程安全互斥锁进行低级访问
function ToJson(HumanReadable: boolean = false): RawUtf8;
将存储的值保存为UTF-8编码的JSON对象
procedure AddItem(const Value: variant);
*将value
添加到内部TDocVariant
文档数组
- 不应与其他基于文档的替代方案(如
Exists
/AddExistingPropOrLock
或AddExistingProp
)结合使用*
procedure AddNewProp(const Name: RawUtf8; const Value: variant; var Obj: variant);
*将属性value
添加到给定的TDocVariant
文档对象
- 此方法在调用时不会期望资源被锁定,与
AddNewPropAndUnlock
不同 - 将使用内部
lock
确保线程安全 - 如果Name已存在,将更新/更改现有的
value
- 可以这样使用,以实现线程安全的缓存:
if not cache.AddExistingProp('Articles',Scope) then
cache.AddNewProp('Articles',GetArticlesFromDB,Scope);
这里GetArticlesFromDB会在主lock
之外执行
procedure AddNewPropAndUnlock(const Name: RawUtf8; const Value: variant; var Obj: variant);
*将属性value
添加到给定的TDocVariant
文档对象以及内部存储的文档,然后释放之前的lock
- 调用此方法之前应由
AddExistingPropOrLock
()返回false,即在一个已锁定的实例上执行*
procedure Clear;
删除所有存储的属性
procedure ReplaceAndUnlock(const Name: RawUtf8; const Value: Variant; out LocalValue: Variant);
*通过属性名称设置value
,并设置本地副本
- 可以这样使用,以实现线程安全的缓存:
if not cache.ExistsOrLock('prop',local) then
cache.ReplaceAndUnlock('prop',newValue,local);
- 调用此方法之前应由
ExistsOrLock
()返回false,即在一个已锁定的实例上执行
property Value[const Name: RawUtf8]: Variant read GetValue write SetValue;
*通过此属性安全地访问文档字段
- 这是此存储的主要入口点
- 如果在读取时Name不存在,将引发
EDocVariant
异常 - 实现类将对variant
value
进行线程安全的副本*
1.3.6. TLockedDocVariant
TLockedDocVariant = class(TInterfacedObjectWithCustomCreate)
*允许线程安全地访问TDocVariant
文档
- 此类从
TInterfacedObjectWithCustomCreate
继承,因此您可以定义一个mormot.core.interfaces.pasTInjectableObject
的已发布属性为ILockedDocVariant
,以便此类可以自动注入*
constructor Create(options: TDocVariantOptions); reintroduce; overload;
使用相应的选项初始化线程安全的文档存储
constructor Create(options: TDocVariantModel); reintroduce; overload;
从给定的模板初始化线程安全的文档存储
constructor Create; overload; override;
*使用快速的TDocVariant
初始化线程安全的文档
- 即调用
Create
(true)或Create
(JSON_FAST
) - 这将是
TInterfacedObjectWithCustomCreate
的默认构造函数,例如在IoC/DI解析期间调用*
destructor Destroy; override;
销毁存储
function AddExistingProp(const Name: RawUtf8; var Obj: variant): boolean;
*向给定的TDocVariant
文档对象添加一个已存在的属性value
- 如果Name存在,则返回TRUE并将Name/
Value
对添加到Obj - 如果存储的文档中不存在Name,则返回FALSE
- 此方法在查找Name期间会使用
lock
,但无论是否返回FALSE,总是会释放lock
(参见AddExistingPropOrLock
)*
function AddExistingPropOrLock(const Name: RawUtf8; var Obj: variant): boolean;
*向给定的TDocVariant
文档对象添加一个已存在的属性value
- 如果Name存在,则返回TRUE并将Name/
Value
对添加到Obj - 如果存储的文档中不存在Name,则返回FALSE,并期望最终调用Lock.Leave或
AddNewPropAndUnlock
()
function Copy: variant;
对内部TDocVariant
文档对象或数组进行线程安全的复制
function Exists(const Name: RawUtf8; out Value: Variant): boolean;
按名称检查和返回一个给定的属性
function ExistsOrLock(const Name: RawUtf8; out Value: Variant): boolean;
*按名称检查和返回一个给定的属性
- 如果找到,则返回TRUE并返回现有Name的
value
- 如果未找到,则返回FALSE,并期望最终调用Lock.Leave或
ReplaceAndUnlock
()
function Lock: TAutoLocker;
对关联的线程安全互斥锁进行低级访问
function ToJson(HumanReadable: boolean = false): RawUtf8;
*将存储的value
保存为UTF-8编码的JSON对象
- 仅仅是
VariantSaveJson
()的包装*
procedure AddItem(const Value: variant);
将value
添加到内部TDocVariant
文档数组
procedure AddNewProp(const Name: RawUtf8; const Value: variant; var Obj: variant);
*向给定的TDocVariant
文档对象添加一个属性value
- 此方法在调用时不会期望资源被锁定,与
AddNewPropAndUnlock
不同 - 将使用内部
lock
确保线程安全 - 如果Name已存在,将更新/更改现有的
value
*
procedure AddNewPropAndUnlock(const Name: RawUtf8; const Value: variant; var Obj: variant);
向给定的TDocVariant
文档对象和内部存储的文档添加一个属性value
procedure Clear;
删除所有存储的属性
procedure ReplaceAndUnlock(const Name: RawUtf8; const Value: Variant; out LocalValue: Variant);
通过属性名称设置value
,并设置本地副本
property Value[const Name: RawUtf8]: variant read GetValue write SetValue;
*将通过此属性安全地访问文档字段
- 如果Name不存在,将引发
EDocVariant
异常 - 返回的variant结果是副本,不是varByRef,因为副本将更具线程安全性*
1.3.7. TThreadAbstract
TThreadAbstract = class(TThread)
*所有TThread继承类的抽象父类
- 利用跨编译器和跨版本RTL的差异
- 拥有预期的Start和TerminateSet方法,以及Terminated属性*
procedure Start;
*调用此方法以start
线程
- Resume在最新的RTL中已被弃用,因为一些操作系统(例如Linux)没有实现此暂停/恢复功能;我们在此为Delphi的旧版本定义此方法*
procedure Terminate; reintroduce;
重新引入以调用TerminatedSet
procedure TerminatedSet; virtual;
*正确terminate
线程
- 由重新引入的
Terminate
调用*
property Terminated;
定义为public,因为可能用于terminate
处理方法
1.3.8. TSynBackgroundThreadAbstract
TSynBackgroundThreadAbstract = class(TThreadAbstract)
*具有自身执行内容的抽象TThread
- 不应直接使用此类,而应使用
TSynBackgroundThreadMethodAbstract
/TSynBackgroundThreadEvent
/TSynBackgroundThreadMethod
,并提供更方便的回调*
constructor Create(const aThreadName: RawUtf8; const OnBeforeExecute: TOnNotifyThread = nil; const OnAfterExecute: TOnNotifyThread = nil; CreateSuspended: boolean = false); reintroduce;
*初始化线程
- 可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread,或者至少将OnAfterExecute设置为
TSynLogFamily.OnThreadEnded
*
destructor Destroy; override;
*释放使用的资源
- 调用
WaitForNotExecuting
(100)以确保正确终结*
function SleepOrTerminated(MS: cardinal): boolean;
*Sleep()的安全版本,不会中断线程进程
- 如果线程已终止,则返回TRUE
- 如果成功等待了MS毫秒,则返回FALSE*
procedure TerminatedSet; override;
*正确终止线程
- 由重新引入的Terminate调用*
procedure WaitForNotExecuting(maxMS: integer = 500);
*等待Execute/ExecuteLoop结束(即fExecute<>exRun)
- 在循环中调用Sleep(),直到达到超时
- 例如在
Destroy
中使用,以避免任何GPF并确保干净地终结*
property Pause: boolean read fExecuteLoopPause write SetExecuteLoopPause;
*临时停止ExecuteLoop的执行,直到设置为false
- 例如可由
TSynBackgroundTimer
使用,以延迟后台任务的进程*
property ProcessEvent: TSynEvent read fProcessEvent;
*访问与低级别相关的事件,用于通知后台线程任务执行
- 可以调用ProcessEvent.SetEvent来触发内部处理循环*
1.3.9. TSynBackgroundThreadMethodAbstract
TSynBackgroundThreadMethodAbstract = class(TSynBackgroundThreadAbstract)
*抽象TThread,能够在其自己的执行内容中运行方法
- 典型用途是用于处理数据或远程访问的后台线程,同时UI将保持响应,通过在循环中运行OnIdle事件:例如,查看mormot.rest.client.pas单元中
TRestClientUri.OnIdle
如何处理这种情况 - 不应直接使用此类,而应从中继承并重写Process方法,或使用
TSynBackgroundThreadEvent
/TSynBackgroundThreadMethod
并提供更方便的回调*
constructor Create(const aOnIdle: TOnIdleSynBackgroundThread; const aThreadName: RawUtf8; const OnBeforeExecute: TOnNotifyThread = nil; const OnAfterExecute: TOnNotifyThread = nil); reintroduce;
*初始化线程
- 如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到
RunAndWait
()返回 - 可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread*
destructor Destroy; override;
终结线程
function RunAndWait(OpaqueParam: pointer): boolean;
*在后台线程中异步启动Process抽象方法
- 等待进程完成,同时调用
OnIdle
()回调 - 在后台线程中引发的任何异常都将在调用者线程中转换
- 如果self未设置,或者从当前正在处理的同一线程中调用(以避免从
OnIdle
()回调引发的竞态条件),则返回false - 当后台进程完成时返回true
- OpaqueParam将用于指定后台进程的线程安全内容
- 此方法是线程安全的,即它将等待由另一个线程启动的任何进程:可以从任何线程调用此方法,即使其主要目的是从主UI线程调用*
property OnAfterProcess: TOnNotifyThread read fOnAfterProcess write fOnAfterProcess;
在每个Process之后在Execute中触发的可选回调事件
property OnBeforeProcess: TOnNotifyThread read fOnBeforeProcess write fOnBeforeProcess;
在每个Process之前在Execute中触发的可选回调事件
property OnIdle: TOnIdleSynBackgroundThread read fOnIdle write fOnIdle;
*在远程阻塞进程期间循环执行的回调事件,例如,在请求时间较长时刷新UI
- 可以为此属性分配一个回调,例如调用Application.ProcessMessages,在后台线程中执行远程请求,但让UI保持响应:mORMotUILogin.pas中的TLoginForm.OnIdleProcess和OnIdleProcessForm方法将满足此属性的预期
- 如果
OnIdle
未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait
()返回*
property OnIdleBackgroundThreadActive: boolean read GetOnIdleBackgroundThreadActive;
*如果后台线程处于活动状态,并且在处理过程中调用了OnIdle
事件,则为TRUE
- 例如,用于确保用户界面消息不会重新进入*
1.3.10. TSynBackgroundThreadEvent
TSynBackgroundThreadEvent = class(TSynBackgroundThreadMethodAbstract)
允许后台线程处理方法回调
constructor Create(const aOnProcess: TOnProcessSynBackgroundThread; const aOnIdle: TOnIdleSynBackgroundThread; const aThreadName: RawUtf8); reintroduce;
*初始化线程
- 如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回*
property OnProcess: TOnProcessSynBackgroundThread read fOnProcess write fOnProcess;
*提供一个在后台线程中执行的方法处理程序
- 由RunAndWait()方法触发 - 该方法将等待直到完成
- 在RunAndWait()中指定的OpaqueParam将在此处提供*
1.3.11. TSynBackgroundThreadMethod
TSynBackgroundThreadMethod = class(TSynBackgroundThreadMethodAbstract)
允许后台线程处理可变的TThreadMethod回调
procedure RunAndWait(Method: TThreadMethod); reintroduce;
*运行一次提供的TThreadMethod回调
- 使用此方法,而不是继承的
RunAndWait
()*
1.3.12. TSynBackgroundThreadProcedure
TSynBackgroundThreadProcedure = class(TSynBackgroundThreadMethodAbstract)
允许后台线程处理过程回调
constructor Create(aOnProcess: TOnProcessSynBackgroundThreadProc; const aOnIdle: TOnIdleSynBackgroundThread; const aThreadName: RawUtf8); reintroduce;
*初始化线程
- 如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回*
property OnProcess: TOnProcessSynBackgroundThreadProc read fOnProcess write fOnProcess;
*提供一个在后台线程中执行的过程处理程序
- 由RunAndWait()方法触发 - 该方法将等待直到完成
- 在RunAndWait()中指定的OpaqueParam将在此处提供*
1.3.13. TSynBackgroundThreadProcess
TSynBackgroundThreadProcess = class(TSynBackgroundThreadAbstract)
能够在给定周期速率下运行方法的TThread
constructor Create(const aThreadName: RawUtf8; const aOnProcess: TOnSynBackgroundThreadProcess; aOnProcessMS: cardinal; const aOnBeforeExecute: TOnNotifyThread = nil; const aOnAfterExecute: TOnNotifyThread = nil; aStats: TSynMonitorClass = nil; CreateSuspended: boolean = false); reintroduce; virtual;
*初始化线程以进行周期性任务处理
- 当调用ProcessEvent.SetEvent或自上次处理以来已经过去了aOnProcessMS毫秒周期时,将调用aOnProcess
- 如果aOnProcessMS为0,将等待直到调用ProcessEvent.SetEvent
- 可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread*
destructor Destroy; override;
终结线程并等待其结束
property OnException: TNotifyEvent read fOnException write fOnException;
*当OnProcess
引发异常时执行的事件回调
- 提供的Sender参数是引发的异常实例*
property OnProcess: TOnSynBackgroundThreadProcess read fOnProcess;
访问周期性任务的实现事件
property OnProcessMS: cardinal read fOnProcessMS write fOnProcessMS;
访问周期性任务处理的延迟(以毫秒为单位)
property Stats: TSynMonitor read fStats;
*处理统计信息
- 如果在类构造函数中aStats为nil,则可能为nil*
1.3.14. TSynBackgroundTimerTask
TSynBackgroundTimerTask = record
由TSynBackgroundTimer
内部注册列表使用
1.3.15. TSynBackgroundTimer
TSynBackgroundTimer = class(TSynBackgroundThreadProcess)
*能够在后台线程中以周期速率运行一个或多个任务的TThread
- 例如,通过继承的
TRestBackgroundTimer
,由TRest.TimerEnable
/TimerDisable方法使用 - 每个进程可以有自己的
text
消息FIFO队列 - 如果你
expect
更新某些GUI,你应该使用TTimer组件(例如,周期为200ms),因为TSynBackgroundTimer
将使用自己的独立线程*
constructor Create(const aThreadName: RawUtf8; const aOnBeforeExecute: TOnNotifyThread = nil; aOnAfterExecute: TOnNotifyThread = nil; aStats: TSynMonitorClass = nil; aLogClass: TSynLogClass = nil); reintroduce; virtual;
*初始化线程以进行周期性task
processing
- 你可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread,如
TRestBackgroundTimer.Create
所做的那样*
destructor Destroy; override;
终结线程
function DeQueue(const aOnProcess: TOnSynBackgroundTimerProcess; const aMsg: RawUtf8): boolean;
*从processing
列表中移除一条消息
- 提供的消息将在与aOnProcess相关联的内部FIFO列表中搜索,如果找到则从列表中移除
- aOnProcess应通过之前的调用到
Enable
()方法进行注册 - 如果成功则返回true,如果提供的消息未注册则返回false*
function Disable(const aOnProcess: TOnSynBackgroundTimerProcess): boolean;
*取消定义一个在周期秒数上运行的task
- aOnProcess应通过之前的调用到
Enable
()方法进行注册 - 如果成功则返回true,如果提供的
task
未注册则返回false - 对于mORMot服务上的后台进程,考虑使用
TRestServer
的TimerEnable/TimerDisable方法及其TSynBackgroundTimer
线程*
function EnQueue(const aOnProcess: TOnSynBackgroundTimerProcess; const aMsgFmt: RawUtf8; const Args: array of const; aExecuteNow: boolean = false): boolean; overload;
*在task
的下次执行期间添加一条格式化消息进行处理
- 提供的消息将被添加到与aOnProcess相关联的内部FIFO列表中,然后每次调用时作为aMsg参数提供
- 如果aExecuteNow为true,则不会等待下一个aOnProcessSecs的发生
- aOnProcess应通过之前的调用到
Enable
()方法进行注册 - 如果成功则返回true,如果提供的
task
未注册则返回false*
function EnQueue(const aOnProcess: TOnSynBackgroundTimerProcess; const aMsg: RawUtf8; aExecuteNow: boolean = false): boolean; overload;
*在task
的下次执行期间添加一条消息进行处理
- 提供的消息将被添加到与aOnProcess相关联的内部FIFO列表中,然后每次调用时作为aMsg参数提供
- 如果aExecuteNow为true,则不会等待下一个aOnProcessSecs的发生
- aOnProcess应通过之前的调用到
Enable
()方法进行注册 - 如果成功则返回true,如果提供的
task
未注册则返回false*
function ExecuteNow(const aOnProcess: TOnSynBackgroundTimerProcess): boolean;
*立即执行一个task
,不等待下一个aOnProcessSecs的发生
function ExecuteOnce(const aOnProcess: TOnSynBackgroundTimerProcess): boolean;
*立即执行一个task
,不等待下一个aOnProcessSecs的发生
- aOnProcess不应通过之前的调用到
Enable
()方法进行注册*
procedure Enable(const aOnProcess: TOnSynBackgroundTimerProcess; aOnProcessSecs: cardinal);
*定义一个在周期秒数上运行的task
的处理方法
- 对于mORMot服务上的后台进程,考虑使用
TRest
的TimerEnable/TimerDisable方法及其关联的BackgroundTimer线程*
procedure WaitUntilNotProcessing(timeoutsecs: integer = 10);
等待直到没有后台task
正在处理
property Processing: boolean read fProcessing;
如果当前正在处理某些tasks
,则返回TRUE
property Task: TSynBackgroundTimerTaskDynArray read fTask;
对内部task
列表的低级访问
property Tasks: TDynArrayLocked read fTasks;
对内部task
列表的线程安全包装的低级访问 Low-level access to the internal task
list wrapper and safe
1.3.16. TBlockingProcess
TBlockingProcess = class(TSynEvent)
A semaphore used to wait for some process to be finished
- used e.g. by TBlockingCallback
in mormot.rest.server.pas
- once created, process would block via a WaitFor call, which would be released when NotifyFinished is called by the process background thread
constructor Create(aTimeOutMs: integer); reintroduce; overload; virtual;
Initialize the semaphore instance
- specify a time out milliseconds period after which blocking execution should be handled as failure (if 0 is set, default 3000 would be used)
- an associated mutex would be created and owned by this instance
constructor Create(aTimeOutMs: integer; aSafe: PSynLocker); reintroduce; overload; virtual;
Override to reset
associated params initialize the semaphore instance
- specify a time out milliseconds period after which blocking execution should be handled as failure (if 0 is set, default 3000 would be used)
- an associated mutex shall be supplied
destructor Destroy; override;
Finalize the instance
function NotifyFinished(alreadyLocked: boolean = false): boolean; virtual;
Should be called by the background process when it is finished
- the caller would then let its WaitFor
method return
- returns TRUE on success (i.e. status was not evRaised or evTimeout)
- if the instance is already locked (e.g. when retrieved from TBlockingProcessPool.FromCallLocked), you may set alreadyLocked=TRUE
function Reset: boolean; virtual;
Just a wrapper to reset
the internal Event
state to evNone
- may be used to re-use the same TBlockingProcess
instance, after a successfull WaitFor
/NotifyFinished
process
- returns TRUE on success (i.e. status was not evWaiting), setting the current state to evNone, and the Call property to 0
- if there is a WaitFor
currently in progress, returns FALSE
function WaitFor: TBlockingEvent; reintroduce; overload; virtual;
Called to wait for NotifyFinished
() to be called, or trigger timeout
- returns the final state of the process, i.e. evRaised or evTimeOut
function WaitFor(TimeOutMS: integer): TBlockingEvent; reintroduce; overload;
Called to wait for NotifyFinished
() to be called, or trigger timeout
- returns the final state of the process, i.e. evRaised or evTimeOut
procedure Lock;
Just a wrapper around fSafe^.Lock
procedure Unlock;
Just a wrapper around fSafe^.Unlock
property Event: TBlockingEvent read fEvent;
The current state of process
- use Reset
method to re-use this instance after a WaitFor
process
property TimeOutMs: integer read fTimeOutMS;
The time out period, in ms, as defined at constructor level
1.3.17. TBlockingProcessPoolItem
TBlockingProcessPoolItem = class(TBlockingProcess)
A semaphore used in the TBlockingProcessPool
- such semaphore have a Call field to identify each execution
property Call: TBlockingProcessPoolCall read fCall;
An unique identifier, when owned by a TBlockingProcessPool
- Reset would restore this field to its 0 default value
1.3.18. TBlockingProcessPool
TBlockingProcessPool = class(TSynPersistent)
Manage a pool of TBlockingProcessPoolItem
instances
- each call will be identified via a TBlockingProcessPoolCall
unique value
- to be used to emulate e.g. blocking execution from an asynchronous event-driven DDD process
- it would also allow to re-use TEvent
system resources
constructor Create(aClass: TBlockingProcessPoolItemClass = nil); reintroduce;
Set TBlockingProcessPoolItem.Call
initialize the pool, for a given implementation class
destructor Destroy; override;
Finalize the pool
- would also force all pending WaitFor to trigger a evTimeOut
function FromCall(call: TBlockingProcessPoolCall; locked: boolean = false): TBlockingProcessPoolItem; virtual;
Retrieve a TBlockingProcess
from its call identifier
- may be used e.g. from the callback of the asynchronous process to set some additional parameters to the inherited TBlockingProcess
, then call NotifyFinished to release the caller WaitFor
- if leavelocked is TRUE, the returned instance would be locked: caller should execute result.Unlock or NotifyFinished(true) after use
function NewProcess(aTimeOutMs: integer): TBlockingProcessPoolItem; virtual;
Book a TBlockingProcess
from the internal pool
- returns nil on error (e.g. the instance is destroying)
- or returns the blocking process instance corresponding to this call; its Call property would identify the call for the asynchronous callback, then after WaitFor, the Reset method should be run to release the mutex for the pool
1.3.19. TSynParallelProcessThread
TSynParallelProcessThread = class(TSynBackgroundThreadMethodAbstract)
Thread executing process for TSynParallelProcess
1.3.20. TSynParallelProcess
TSynParallelProcess = class(TSynPersistentLock)
Allow parallel execution of an index-based process in a thread pool
- will create its own thread pool, then execute any method by spliting the work into each thread
constructor Create(ThreadPoolCount: integer; const ThreadName: RawUtf8; const OnBeforeExecute: TOnNotifyThread = nil; const OnAfterExecute: TOnNotifyThread = nil; MaxThreadPoolCount: integer = 32); reintroduce; virtual;
Initialize the thread pool
- you could define some callbacks to nest the thread execution, e.g. assigned to TRestServer.BeginCurrentThread/EndCurrentThread
- up to MaxThreadPoolCount=32 threads could be setup (you may allow a bigger value, but interrest of this thread pool is to have its process saturating each CPU core)
- if ThreadPoolCount
is 0, no thread would be created, and process would take place in the current thread
destructor Destroy; override;
Finalize the thread pool
procedure ParallelRunAndWait(const Method: TOnSynParallelProcess; MethodCount: integer; const OnMainThreadIdle: TNotifyEvent = nil);
Run a method in parallel, and wait for the execution to finish
- will split
Method[0..MethodCount-1] execution over the threads
- in case of any exception during process, an ESynParallel exception would be raised by this method
- if OnMainThreadIdle is set, the current thread (which is expected to be e.g. the main UI thread) won't process anything, but call this event during waiting for the background threads
property ParallelRunCount: integer read fParallelRunCount;
How many threads have been activated
property ThreadName: RawUtf8 read fThreadName;
Some text
identifier, used to distinguish each owned thread
property ThreadPoolCount: integer read fThreadPoolCount;
How many threads are currently in this instance thread pool
1.3.21. TSynThread
TSynThread = class(TThreadAbstract)
A simple TThread with a "Terminate" event run in the thread context
- the TThread.OnTerminate event is run within Synchronize() so did not match our expectations to be able to release the resources in the thread context which created them (e.g. for COM objects, or some DB drivers)
- used internally by THttpServerGeneric.NotifyThreadStart() - you should not have to use the protected fOnThreadTerminate event handler
- also define a Start method for compatibility with older versions of Delphi
constructor Create(CreateSuspended: boolean); reintroduce; virtual;
Initialize the thread instance, in non suspended state
function SleepOrTerminated(MS: cardinal): boolean;
Safe version of Sleep() which won't break the thread process
- returns TRUE if the thread was Terminated
- returns FALSE if successfully waited up to MS milliseconds
property StartNotified: TObject read fStartNotified write fStartNotified;
Ensure fOnThreadTerminate is called only if NotifyThreadStart has been done
1.3.22. TNotifiedThread
TNotifiedThread = class(TSynThread)
Abstract class to implement a thread with start/stop notifications
- e.g. a server thread
- do not use this class, but rather the THttpServer
, THttpApiServer
or TWebSocketServer
(as defined in mormot.net.websock)
constructor Create(CreateSuspended: boolean; const OnStart, OnStop: TOnNotifyThread; const ProcessName: RawUtf8); reintroduce; virtual;
Initialize the server instance, in non suspended state
procedure SetServerThreadsAffinityPerCpu( const log: ISynLog; const threads: TThreadDynArray);
Assign each thread to a single logical CPU core
- for instance, for a HTTP
server, it may ensure better scalability with short-living requests and high number of threads
procedure SetServerThreadsAffinityPerSocket( const log: ISynLog; const threads: TThreadDynArray);
Assign each thread to a single hardware CPU socket
- for instance, for a HTTP
server, it may ensure better scalability on complex hardware with several physical CPU packages - but it is very picky, so should be enabled only with proper testing on the actual HW
1.3.23. TLoggedThread
TLoggedThread = class(TSynThread)
Abstract class to implement a thread with logging notifications
constructor Create(CreateSuspended: boolean; Logger: TSynLogClass; const ProcName: RawUtf8); reintroduce; virtual;
Initialize the server instance, in non suspended state
procedure TerminateAndWaitFinished(TimeOutMs: integer = 5000); virtual;
Notify the thread to be terminated, and wait for DoExecute to finish
property LogClass: TSynLogClass read fLogClass;
The associated logging class
property ProcessName: RawUtf8 read fProcessName;
The name of this thread, as supplied to SetCurrentThreadName
()
1.3.24. TLoggedWorkThread
TLoggedWorkThread = class(TLoggedThread)
A class able to run some process in a background thread
- with proper logging and eventual ending notification
constructor Create(Logger: TSynLogClass; const ProcessName: RawUtf8; const NameValuePairs: array of const; const OnExecute: TOnLoggedWorkProcess; const OnExecuted: TNotifyEvent = nil); reintroduce; overload;
This constructor will directly start the thread in background
- with the context as a TDocVariantData
object with name/value pairs
constructor Create(Logger: TSynLogClass; const ProcessName: RawUtf8; Sender: TObject; const OnExecute: TNotifyEvent; const OnExecuted: TNotifyEvent = nil); reintroduce; overload;
This constructor will directly start the thread in background
- with the context as a regular TNotifyEvent
1.3.25. TSynThreadPoolWorkThread
TSynThreadPoolWorkThread = class(TSynThread)
Defines the work threads used by TSynThreadPool
constructor Create(Owner: TSynThreadPool); reintroduce;
Exception-safe call of fOwner.Task() initialize the thread
destructor Destroy; override;
Finalize the thread
procedure Execute; override;
Will loop for any pending task, and execute fOwner.Task()
property Owner: TSynThreadPool read fOwner;
The associated thread pool
1.3.26. TSynThreadPool
TSynThreadPool = class(TObject)
A simple Thread Pool, used e.g. for fast handling HTTP
/1.0 requests
- implemented over I/O Completion Ports under Windows, or a classical Event-driven approach under Linux/POSIX
constructor Create(NumberOfThreads: integer = 32; aOverlapHandle: THandle = INVALID_HANDLE_VALUE; const aName: RawUtf8 = '');
Initialize a thread pool with the supplied number of threads
- abstract Task() virtual method will be called by one of the threads
- up to 256 threads can be associated to a Thread Pool
- on Windows, can optionaly accept aOverlapHandle - a handle previously opened using Windows Overlapped I/O (IOCP)
- on POSIX, aQueuePendingContext=true will store
the pending context into an internal queue, so that Push
() returns true until the queue is full
destructor Destroy; override;
Shut down the Thread pool, releasing all associated threads
function Push(aContext: pointer; aWaitOnContention: boolean = false): boolean;
Let a task (specified as a pointer) be processed by the Thread Pool
- returns false if there is no idle thread available in the pool and Create
(aQueuePendingContext=false) was used (caller should retry later); if aQueuePendingContext was true in Create
, or IOCP is used, the supplied context will be added to an internal list and handled when possible
- if aWaitOnContention is default false, returns immediately when the queue is full; set aWaitOnContention=true to wait up to ContentionAbortDelay
ms and retry to queue the task
property ContentionAbortCount: cardinal read fContentionAbortCount;
How many tasks were rejected due to thread pool contention
- if this number is high, consider setting a higher number of threads, or profile and tune the Task method
property ContentionAbortDelay: integer read fContentionAbortDelay write fContentionAbortDelay;
Milliseconds delay to reject a connection due to contention
- default is 5000, i.e. 5 seconds wait for some room to be available in the IOCP or aQueuePendingContext internal list
- during this delay, no new connection is available (i.e. Accept is not called), so that a load balancer could detect the contention and switch to another instance in the pool, or a direct client may eventually have its connection rejected, so won't start sending data
property ContentionCount: cardinal read fContentionCount;
How many times the pool waited for an available slot in the queue
- contention won't fail immediately, but will retry until ContentionAbortDelay
- any high number here may better increase the threads count
- use this property and ContentionTime
to compute the average contention time
property ContentionTime: Int64 read fContentionTime;
Total milliseconds spent waiting for an available slot in the queue
- contention won't fail immediately, but will retry until ContentionAbortDelay
- any high number here requires code refactoring of the Task method
property RunningThreads: integer read fRunningThreads;
How many threads are currently processing tasks in this thread pool
- is in the range 0..WorkThreadCount
property WorkThread: TSynThreadPoolWorkThreads read fWorkThread;
Low-level access to the threads defined in this thread pool
property WorkThreadCount: integer read fWorkThreadCount;
How many threads are available in the pool
- maps Create
() parameter, i.e. 32 by default
1.4. Types implemented in the mormot.core.threads unit
1.4.1. TBlockingEvent
TBlockingEvent = ( evNone, evWaiting, evTimeOut, evRaised );
The current state of a TBlockingProcess
instance
1.4.2. TBlockingProcessPoolCall
TBlockingProcessPoolCall = type integer;
Used to identify each TBlockingProcessPool
call
- allow to match a given TBlockingProcessPoolItem
semaphore
1.4.3. TBlockingProcessPoolItemClass
TBlockingProcessPoolItemClass = class of TBlockingProcessPoolItem;
Class-reference type (metaclass) of a TBlockingProcess
1.4.4. TEvent
TEvent = syncobjs.TEvent;
Defined here to avoid explicit link to syncobjs in uses clause
- note that you may better use TSynEvent
from mormot.core.os.pas
1.4.5. TOnIdleSynBackgroundThread
TOnIdleSynBackgroundThread = procedure(Sender: TSynBackgroundThreadAbstract; ElapsedMS: integer) of object;
Idle method called by TSynBackgroundThreadAbstract
in the caller thread during remote blocking process in a background thread
- typical use is to run Application.ProcessMessages, e.g. for TRestClientUri.Uri
() to provide a responsive UI even in case of slow blocking remote access
- provide the time elapsed (in milliseconds) from the request start (can be used e.g. to popup a temporary message to wait)
- is call once with ElapsedMS=0 at request start
- is call once with ElapsedMS=-1 at request ending
- see TLoginForm.OnIdleProcess and OnIdleProcessForm in mORMotUILogin.pas
1.4.6. TOnLoggedWorkProcess
TOnLoggedWorkProcess = procedure(const Context: TDocVariantData) of object;
Event called in a background thread by TLoggedWorkThread.Create
1.4.7. TOnNotifyThread
TOnNotifyThread = procedure(Sender: TThread) of object;
Event prototype used e.g. by TSynBackgroundThreadAbstract
and TSynThread
callbacks
1.4.8. TOnProcessSynBackgroundThread
TOnProcessSynBackgroundThread = procedure(Sender: TSynBackgroundThreadEvent; ProcessOpaqueParam: pointer) of object;
Background process method called by TSynBackgroundThreadEvent
- will supply the OpaqueParam parameter as provided to RunAndWait() method when the Process virtual method will be executed
1.4.9. TOnProcessSynBackgroundThreadProc
TOnProcessSynBackgroundThreadProc = procedure(ProcessOpaqueParam: pointer);
Background process procedure called by TSynBackgroundThreadProcedure
- will supply the OpaqueParam parameter as provided to RunAndWait() method when the Process virtual method will be executed
1.4.10. TOnSynBackgroundThreadProcess
TOnSynBackgroundThreadProcess = procedure(Sender: TSynBackgroundThreadProcess) of object;
Event callback executed periodically by TSynBackgroundThreadProcess
1.4.11. TOnSynBackgroundTimerProcess
TOnSynBackgroundTimerProcess = procedure(Sender: TSynBackgroundTimer; const Msg: RawUtf8) of object;
Event callback executed periodically by TSynBackgroundThreadProcess
- Msg is '' if there is no pending message in this task FIFO
- Msg is set for each pending message in this task FIFO
- on mORMot 1, there was a TWaitEvent parameter which is now removed
1.4.12. TOnSynParallelProcess
TOnSynParallelProcess = procedure(IndexStart, IndexStop: integer) of object;
Callback implementing some parallelized process for TSynParallelProcess
- if 0<=IndexStart<=IndexStop, it should execute some process
1.4.13. TPendingTaskListItemDynArray
TPendingTaskListItemDynArray = array of TPendingTaskListItem;
Internal list definition, used by TPendingTaskList
storage
1.4.14. TSynBackgroundThreadProcessStep
TSynBackgroundThreadProcessStep = ( flagIdle, flagStarted, flagFinished, flagDestroying );
State machine status of the TSynBackgroundThreadAbstract
process
1.4.15. TSynBackgroundThreadProcessSteps
TSynBackgroundThreadProcessSteps = set of TSynBackgroundThreadProcessStep;
State machine statuses of the TSynBackgroundThreadAbstract
process
1.4.16. TSynBackgroundTimerTaskDynArray
TSynBackgroundTimerTaskDynArray = array of TSynBackgroundTimerTask;
Protect Msg[] list stores TSynBackgroundTimer
internal registration list
1.4.17. TThreadDynArray
TThreadDynArray = array of TThread;
A dynamic array of TThread
1.4.18. TWaitResult
TWaitResult = syncobjs.TWaitResult;
Defined here to avoid explicit link to syncobjs in uses clause
- note that you may better use TSynEvent
from mormot.core.os.pas
1.5. Constants implemented in the mormot.core.threads unit
1.5.1. THREADPOOL_MAXTHREADS
THREADPOOL_MAXTHREADS = 256;
Allow up to 256 * 2MB = 512MB of RAM for the TSynThreadPoolWorkThread
stack
1.5.2. wrSignaled
wrSignaled = syncobjs.wrSignaled;
Please favor TSynEvent
from mormot.core.os instead of TEvent
defined here to avoid explicit link to syncobjs in uses clause
热门相关:我的绝色美女房客 傲娇小萌妃:殿下太腹黑 我的全世界就是你 穹顶之上 兵王传说