274 lines
8.9 KiB
ObjectPascal
274 lines
8.9 KiB
ObjectPascal
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.
|