unit nsThreadUtils; {$MACRO on} {$IFDEF Windows} {$DEFINE extdecl:=stdcall} {$ELSE Windows} {$DEFINE extdecl:=cdecl} {$ENDIF} interface uses nsXPCOM, nsTypes, nsGeckoStrings; type nsIEnvironment = interface; nsIEventTarget = interface; nsIProcess = interface; nsIRunnable = interface; nsISupportsPriority = interface; nsIThread = interface; nsIThreadInternal = interface; nsIThreadObserver = interface; nsIThreadEventFilter = interface; nsIThreadManager = interface; nsIThreadPoolListener = interface; nsIThreadPool = interface; nsITimer = interface; nsIEnvironment = interface(nsISupports) ['{101d5941-d820-4e85-a266-9a3469940807}'] procedure _set(aName: nsAString; aValue: nsAString); safecall; procedure get(aName: nsAString; aResult: nsAString); safecall; function exists(aName: nsAString): PRBool; safecall; end; nsIEventTarget = interface(nsISupports) ['{4e8febe4-6631-49dc-8ac9-308c1cb9b09c}'] procedure dispatch(event: nsIRunnable; flags: PRUint32); safecall; function isOnCurrentThread(): PRBool; safecall; end; nsIProcess = interface(nsISupports) ['{9da0b650-d07e-4617-a18a-250035572ac8}'] procedure init(aExecutable: nsIFile); safecall; procedure initWithPid(aPid: PRUint32); safecall; procedure kill(); safecall; function run(aBlocking: PRBool; aArgs: PAnsiCharArray; aCount: PRUint32): PRUint32; safecall; function getLocation(): nsIFile; safecall; property location: nsIFile read getLocation; function getPid(): PRUint32; safecall; property pid: PRUint32 read getPid; function getProcessName(): PAnsiChar; safecall; property processName: PAnsiChar read getProcessName; function getProcessSignature: PRUint32; safecall; property processSignature: PRUint32 read getProcessSignature; function getExitValue: PRInt32; safecall; property exitValue: PRInt32 read getExitValue; end; nsIRunnable = interface(nsISupports) ['{4a2abaf0-6886-11d3-9382-00104ba0fd40}'] procedure run(); safecall; end; nsISupportsPriority = interface(nsISupports) ['{aa578b44-abd5-4c19-8b14-36d4de6fdc36}'] function getPriority: PRInt32; safecall; procedure setPriority(aValue: PRInt32); safecall; property priority: PRInt32 read getPriority write setPriority; procedure adjustPriority(aDelta: PRInt32); safecall; end; nsIThread = interface(nsIEventTarget) ['{9c889946-a73a-4af3-ae9a-ea64f7d4e3ca}'] function getPRThread: Pointer; safecall; property PRThread: Pointer read getPRThread; procedure shutdown(); safecall; function hasPendingEvents(): PRBool; safecall; function processNextEvent(mayWait: PRBool): PRBool; safecall; end; nsIThreadInternal = interface(nsISupports) ['{f89b5063-b06d-42f8-bf23-4dfcf2d80d6a}'] function getObserver: nsIThreadObserver; safecall; procedure setObserver(aValue: nsIThreadObserver); safecall; property observer: nsIThreadObserver read getObserver write setObserver; procedure pushEventQueue(aFilter: nsIThreadEventFilter); safecall; procedure popEventQueue(); safecall; end; nsIThreadObserver = interface(nsISupports) ['{81D0B509-F198-4417-8020-08EB4271491F}'] procedure onDispatchedEvent(aThread: nsIThreadInternal); safecall; procedure onProcessNextEvent(aThread: nsIThreadInternal; aMayWait: PRBool; aRecursionDepth: PRUint32); safecall; procedure afterProcessNextEvent(aThread: nsIThreadInternal; aRecursionDepth: PRUint32); safecall; end; nsIThreadEventFilter = interface(nsISupports) ['{a0605c0b-17f5-4681-b8cd-a1cd75d42559}'] function acceptEvent(aEvent: nsIRunnable): PRBool; extdecl; end; nsIThreadManager = interface(nsISupports) ['{056216f5-8803-46b4-9199-d95bc1f0446f}'] function newThread(creationFlag: PRUint32): nsIThread; safecall; function getThreadFromPRThread(prthread: Pointer): nsIThread; safecall; function getMainThread(): nsIThread; safecall; property mainThread: nsIThread read getMainThread; function getCurrentThread: nsIThread; safecall; property currentThread: nsIThread read getCurrentThread; function getIsMainThread: PRBool; safecall; property isMainThread: PRbool read getIsMainThread; end; nsIThreadPoolListener = interface(nsISupports) ['{ef194cab-3f86-4b61-b132-e5e96a79e5d1}'] procedure onThreadCreated(); safecall; procedure onThreadShuttingDown(); safecall; end; nsIThreadPool = interface(nsIEventTarget) ['{394c29f0-225f-487f-86d3-4c259da76cab}'] procedure shutdown(); safecall; function getThreadLimit(): PRUint32; safecall; procedure setThreadLimit(aValue: PRUint32); safecall; property threadLimit: PRUint32 read getThreadLimit write setThreadLimit; function getIdleThreadLimit(): PRUint32; safecall; procedure setIdleThreadLimit(aValue: PRUint32); safecall; property idleThreadLimit: PRUint32 read getIdleThreadLimit write setIdleThreadLimit; function getIdleThreadTimeout(): PRUint32; safecall; procedure setIdleThreadTimeout(aValue: PRUint32); safecall; property idleThreadTimeout: PRUint32 read getIdleThreadTimeout write setIdleThreadTimeout; function getListener: nsIThreadPoolListener; safecall; procedure setListener(aValue: nsIThreadPoolListener); safecall; property listener: nsIThreadPoolListener read getListener write setListener; end; nsITimer = interface(nsISupports) ['{a796816d-7d47-4348-9ab8-c7aeb3216a7d}'] procedure notify(aTimer: nsITimer); safecall; end; const NS_IEVENTTARGET_DISPATCH_NORMAL = 0; NS_IEVENTTARGET_DISPATCH_SYNC = 1; NS_ISUPPORTSPRIORITY_PRIORITY_HIGHEST = -20; NS_ISUPPORTSPRIORITY_PRIORITY_HIGH = -10; NS_ISUPPORTSPRIORITY_PRIORITY_NORMAL = 0; NS_ISUPPORTSPRIORITY_PRIORITY_LOW = 10; NS_ISUPPORTSPRIORITY_PRIORITY_LOWEST = 20; const NS_THREADMANAGER_CONTRACTID = '@mozilla.org/thread-manager;1'; NS_DISPATCH_NORMAL = NS_IEVENTTARGET_DISPATCH_NORMAL; NS_DISPATCH_SYNC = NS_IEVENTTARGET_DISPATCH_SYNC; type nsTimerCallbackFunc = procedure (aTimer: nsITimer; aClosure: Pointer); cdecl; function NS_NewThread(aInitialEvent: nsIRunnable = nil): nsIThread; function NS_GetCurrentThread(): nsIThread; function NS_GetMainThread(): nsIThread; function NS_IsMainThread(): PRBool; procedure NS_DispatchToCurrentThread(aEvent: nsIRunnable); procedure NS_DispatchToMainThread(aEvent: nsIRunnable; aDispatchFlags: PRUint32 = NS_DISPATCH_NORMAL); procedure NS_ProcessPendingEvents(aThread: nsIThread; aTimeout: PRUint32 = $ffffffff); // const PR_INTERVAL_NO_TIMEOUT = $ffffffff; function NS_HasPendingEvents(aThread: nsIThread = nil): PRBool; function NS_ProcessNextEvent(aThread: nsIThread = nil; aMayWait: PRBool = True): PRBool; implementation uses nsXPCOMGlue, nsError, mmsystem; function NS_NewThread(aInitialEvent: nsIRunnable): nsIThread; var tm: nsIThreadManager; thread: nsIThread; begin NS_GetService(NS_THREADMANAGER_CONTRACTID, nsIThreadManager, tm); thread := tm.newThread(0); if Assigned(aInitialEvent) then thread.dispatch(aInitialEvent, NS_DISPATCH_NORMAL); Result := thread; end; function NS_GetCurrentThread(): nsIThread; var tm: nsIThreadManager; begin NS_GetService(NS_THREADMANAGER_CONTRACTID, nsIThreadManager, tm); Result := tm.currentThread; end; function NS_GetMainThread(): nsIThread; var tm: nsIThreadManager; begin NS_GetService(NS_THREADMANAGER_CONTRACTID, nsIThreadManager, tm); Result := tm.mainThread; end; function NS_IsMainThread(): PRBool; var tm: nsIThreadManager; begin NS_GetService(NS_THREADMANAGER_CONTRACTID, nsIThreadManager, tm); Result := tm.isMainThread; end; procedure NS_DispatchToCurrentThread(aEvent: nsIRunnable); var tm: nsIThreadManager; thread: nsIThread; begin NS_GetService(NS_THREADMANAGER_CONTRACTID, nsIThreadManager, tm); thread := tm.currentThread; thread.dispatch(aEvent, NS_DISPATCH_NORMAL); end; procedure NS_DispatchToMainThread(aEvent: nsIRunnable; aDispatchFlags: PRUint32); var tm: nsIThreadManager; thread: nsIThread; begin NS_GetService(NS_THREADMANAGER_CONTRACTID, nsIThreadManager, tm); thread := tm.mainThread; thread.dispatch(aEvent, aDispatchFlags); end; procedure NS_ProcessPendingEvents(aThread: nsIThread; aTimeout: PRUint32); var start: PRUint32; processedEvent: PRBool; begin if not Assigned(aThread) then aThread := NS_GetCurrentThread; start := timeGetTime(); while True do begin processedEvent := aThread.processNextEvent(False); if not ProcessedEvent then Break; if (timeGetTime()-start)>aTimeout then Break; end; end; function NS_HasPendingEvents(aThread: nsIThread): PRBool; begin if not Assigned(aThread) then aThread := NS_GetCurrentThread; result := aThread.hasPendingEvents; end; function NS_ProcessNextEvent(aThread: nsIThread; aMayWait: PRBool): PRBool; begin if not Assigned(aThread) then aThread := NS_GetCurrentThread; result := aThread.processNextEvent(aMayWait); end; end.