mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1201037 - coalesce network-events on Windows, r=mcmanus
This commit is contained in:
parent
b3e7671265
commit
45cd0b2833
@ -47,6 +47,10 @@ static decltype(CancelMibChangeNotify2)* sCancelMibChangeNotify2;
|
||||
|
||||
#define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed"
|
||||
|
||||
// period during which to absorb subsequent network change events, in
|
||||
// milliseconds
|
||||
static const unsigned int kNetworkChangeCoalescingPeriod = 1000;
|
||||
|
||||
static void InitIphlpapi(void)
|
||||
{
|
||||
if (!sIphlpapi) {
|
||||
@ -98,9 +102,11 @@ nsNotifyAddrListener::nsNotifyAddrListener()
|
||||
: mLinkUp(true) // assume true by default
|
||||
, mStatusKnown(false)
|
||||
, mCheckAttempted(false)
|
||||
, mShutdownEvent(nullptr)
|
||||
, mCheckEvent(nullptr)
|
||||
, mShutdown(false)
|
||||
, mIPInterfaceChecksum(0)
|
||||
, mAllowChangedEvent(true)
|
||||
, mCoalescingActive(false)
|
||||
{
|
||||
InitIphlpapi();
|
||||
}
|
||||
@ -149,12 +155,30 @@ static void WINAPI OnInterfaceChange(PVOID callerContext,
|
||||
notify->CheckLinkStatus();
|
||||
}
|
||||
|
||||
DWORD
|
||||
nsNotifyAddrListener::nextCoalesceWaitTime()
|
||||
{
|
||||
// check if coalescing period should continue
|
||||
double period = (TimeStamp::Now() - mChangeTime).ToMilliseconds();
|
||||
if (period >= kNetworkChangeCoalescingPeriod) {
|
||||
SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
|
||||
mCoalescingActive = false;
|
||||
return INFINITE; // return default
|
||||
} else {
|
||||
// wait no longer than to the end of the period
|
||||
return static_cast<DWORD>
|
||||
(kNetworkChangeCoalescingPeriod - period);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNotifyAddrListener::Run()
|
||||
{
|
||||
PR_SetCurrentThreadName("Link Monitor");
|
||||
|
||||
mChangedTime = TimeStamp::Now();
|
||||
mStartTime = TimeStamp::Now();
|
||||
|
||||
DWORD waitTime = INFINITE;
|
||||
|
||||
if (!sNotifyIpInterfaceChange || !sCancelMibChangeNotify2) {
|
||||
// For Windows versions which are older than Vista which lack
|
||||
@ -162,7 +186,7 @@ nsNotifyAddrListener::Run()
|
||||
HANDLE ev = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
HANDLE handles[2] = { ev, mShutdownEvent };
|
||||
HANDLE handles[2] = { ev, mCheckEvent };
|
||||
OVERLAPPED overlapped = { 0 };
|
||||
bool shuttingDown = false;
|
||||
|
||||
@ -172,9 +196,11 @@ nsNotifyAddrListener::Run()
|
||||
DWORD ret = NotifyAddrChange(&h, &overlapped);
|
||||
|
||||
if (ret == ERROR_IO_PENDING) {
|
||||
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
ret = WaitForMultipleObjects(2, handles, FALSE, waitTime);
|
||||
if (ret == WAIT_OBJECT_0) {
|
||||
CheckLinkStatus();
|
||||
} else if (!mShutdown) {
|
||||
waitTime = nextCoalesceWaitTime();
|
||||
} else {
|
||||
shuttingDown = true;
|
||||
}
|
||||
@ -194,9 +220,15 @@ nsNotifyAddrListener::Run()
|
||||
false, // no initial notification
|
||||
&interfacechange);
|
||||
|
||||
if (ret == NO_ERROR) {
|
||||
ret = WaitForSingleObject(mShutdownEvent, INFINITE);
|
||||
}
|
||||
do {
|
||||
ret = WaitForSingleObject(mCheckEvent, waitTime);
|
||||
if (!mShutdown) {
|
||||
waitTime = nextCoalesceWaitTime();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
} while (ret != WAIT_FAILED);
|
||||
sCancelMibChangeNotify2(interfacechange);
|
||||
}
|
||||
return NS_OK;
|
||||
@ -231,8 +263,8 @@ nsNotifyAddrListener::Init(void)
|
||||
Preferences::AddBoolVarCache(&mAllowChangedEvent,
|
||||
NETWORK_NOTIFY_CHANGED_PREF, true);
|
||||
|
||||
mShutdownEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
NS_ENSURE_TRUE(mShutdownEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
mCheckEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
NS_ENSURE_TRUE(mCheckEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = NS_NewThread(getter_AddRefs(mThread), this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -249,10 +281,11 @@ nsNotifyAddrListener::Shutdown(void)
|
||||
if (observerService)
|
||||
observerService->RemoveObserver(this, "xpcom-shutdown-threads");
|
||||
|
||||
if (!mShutdownEvent)
|
||||
if (!mCheckEvent)
|
||||
return NS_OK;
|
||||
|
||||
SetEvent(mShutdownEvent);
|
||||
mShutdown = true;
|
||||
SetEvent(mCheckEvent);
|
||||
|
||||
nsresult rv = mThread->Shutdown();
|
||||
|
||||
@ -261,12 +294,33 @@ nsNotifyAddrListener::Shutdown(void)
|
||||
// via its mRunnable
|
||||
mThread = nullptr;
|
||||
|
||||
CloseHandle(mShutdownEvent);
|
||||
mShutdownEvent = nullptr;
|
||||
CloseHandle(mCheckEvent);
|
||||
mCheckEvent = nullptr;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* A network event has been registered. Delay the actual sending of the event
|
||||
* for a while and absorb subsequent events in the mean time in an effort to
|
||||
* squash potentially many triggers into a single event.
|
||||
* Only ever called from the same thread.
|
||||
*/
|
||||
nsresult
|
||||
nsNotifyAddrListener::NetworkChanged()
|
||||
{
|
||||
if (mCoalescingActive) {
|
||||
LOG(("NetworkChanged: absorbed an event (coalescing active)\n"));
|
||||
} else {
|
||||
// A fresh trigger!
|
||||
mChangeTime = TimeStamp::Now();
|
||||
mCoalescingActive = true;
|
||||
SetEvent(mCheckEvent);
|
||||
LOG(("NetworkChanged: coalescing period started\n"));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Sends the given event. Assumes aEventID never goes out of scope (static
|
||||
* strings are ideal).
|
||||
*/
|
||||
@ -517,12 +571,12 @@ nsNotifyAddrListener::CheckLinkStatus(void)
|
||||
}
|
||||
|
||||
if (mLinkUp && (prevCsum != mIPInterfaceChecksum)) {
|
||||
TimeDuration since = TimeStamp::Now() - mChangedTime;
|
||||
TimeDuration since = TimeStamp::Now() - mStartTime;
|
||||
|
||||
// Network is online. Topology has changed. Always send CHANGED
|
||||
// before UP - if allowed to and having cooled down.
|
||||
if (mAllowChangedEvent && (since.ToMilliseconds() > 2000)) {
|
||||
SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
|
||||
NetworkChanged();
|
||||
}
|
||||
}
|
||||
if (prevLinkUp != mLinkUp) {
|
||||
|
@ -60,18 +60,33 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
|
||||
HANDLE mShutdownEvent;
|
||||
|
||||
private:
|
||||
// Returns the new timeout period for coalescing (or INFINITE)
|
||||
DWORD nextCoalesceWaitTime();
|
||||
|
||||
// Called for every detected network change
|
||||
nsresult NetworkChanged();
|
||||
|
||||
HANDLE mCheckEvent;
|
||||
|
||||
// set true when mCheckEvent means shutdown
|
||||
bool mShutdown;
|
||||
|
||||
// This is a checksum of various meta data for all network interfaces
|
||||
// considered UP at last check.
|
||||
ULONG mIPInterfaceChecksum;
|
||||
|
||||
// time of the last sent changed event
|
||||
mozilla::TimeStamp mChangedTime;
|
||||
// start time of the checking
|
||||
mozilla::TimeStamp mStartTime;
|
||||
|
||||
// Network changed events are enabled
|
||||
bool mAllowChangedEvent;
|
||||
|
||||
// Flag set while coalescing change events
|
||||
bool mCoalescingActive;
|
||||
|
||||
// Time stamp for first event during coalescing
|
||||
mozilla::TimeStamp mChangeTime;
|
||||
};
|
||||
|
||||
#endif /* NSNOTIFYADDRLISTENER_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user