mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
Re-implemented PlatformEvents through the new API
This commit is contained in:
@@ -5617,7 +5617,9 @@ int PlatformEvent::park(jlong Millis) {
|
||||
// 1 => 0 : pass - return immediately
|
||||
// 0 => -1 : block; then set _Event to 0 before returning
|
||||
|
||||
guarantee(_ParkHandle != nullptr , "Invariant");
|
||||
if (!UseModernSynchAPI) {
|
||||
guarantee(_ParkHandle != nullptr , "Invariant");
|
||||
}
|
||||
guarantee(Millis > 0 , "Invariant");
|
||||
|
||||
// CONSIDER: defer assigning a CreateEvent() handle to the Event until
|
||||
@@ -5649,25 +5651,37 @@ int PlatformEvent::park(jlong Millis) {
|
||||
// adjust Millis accordingly if we encounter a spurious wakeup.
|
||||
|
||||
const int MAXTIMEOUT = 0x10000000;
|
||||
DWORD rv = WAIT_TIMEOUT;
|
||||
while (_Event < 0 && Millis > 0) {
|
||||
DWORD prd = Millis; // set prd = MAX (Millis, MAXTIMEOUT)
|
||||
if (Millis > MAXTIMEOUT) {
|
||||
prd = MAXTIMEOUT;
|
||||
|
||||
if (UseModernSynchAPI) {
|
||||
while ((v = Atomic::load_acquire(&_Event)) < 0) {
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval(Millis);
|
||||
}
|
||||
::WaitOnAddress(&_Event, &v, sizeof(_Event), Millis);
|
||||
delete phri; // if it is null, harmless
|
||||
}
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval(prd);
|
||||
} else {
|
||||
DWORD rv = WAIT_TIMEOUT;
|
||||
while (_Event < 0 && Millis > 0) {
|
||||
DWORD prd = Millis; // set prd = MAX (Millis, MAXTIMEOUT)
|
||||
if (Millis > MAXTIMEOUT) {
|
||||
prd = MAXTIMEOUT;
|
||||
}
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval(prd);
|
||||
}
|
||||
rv = ::WaitForSingleObject(_ParkHandle, prd);
|
||||
assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
||||
assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed with return value: %lu", rv);
|
||||
if (rv == WAIT_TIMEOUT) {
|
||||
Millis -= prd;
|
||||
}
|
||||
delete phri; // if it is null, harmless
|
||||
}
|
||||
rv = ::WaitForSingleObject(_ParkHandle, prd);
|
||||
assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
||||
assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed with return value: %lu", rv);
|
||||
if (rv == WAIT_TIMEOUT) {
|
||||
Millis -= prd;
|
||||
}
|
||||
delete phri; // if it is null, harmless
|
||||
v = _Event;
|
||||
}
|
||||
v = _Event;
|
||||
_Event = 0;
|
||||
// see comment at end of PlatformEvent::park() below:
|
||||
OrderAccess::fence();
|
||||
@@ -5683,7 +5697,9 @@ void PlatformEvent::park() {
|
||||
// 1 => 0 : pass - return immediately
|
||||
// 0 => -1 : block; then set _Event to 0 before returning
|
||||
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
if (!UseModernSynchAPI) {
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
}
|
||||
// Invariant: Only the thread associated with the Event/PlatformEvent
|
||||
// may call park().
|
||||
// Consider: use atomic decrement instead of CAS-loop
|
||||
@@ -5695,21 +5711,35 @@ void PlatformEvent::park() {
|
||||
guarantee((v == 0) || (v == 1), "invariant");
|
||||
if (v != 0) return;
|
||||
|
||||
// Do this the hard way by blocking ...
|
||||
// TODO: consider a brief spin here, gated on the success of recent
|
||||
// spin attempts by this thread.
|
||||
while (_Event < 0) {
|
||||
// The following code is only here to maintain the
|
||||
// characteristics/performance from when an ObjectMonitor
|
||||
// "responsible" thread used to issue timed parks.
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval((jlong)1);
|
||||
if (UseModernSynchAPI) {
|
||||
while ((v = Atomic::load_acquire(&_Event)) < 0) {
|
||||
// The following code is only here to maintain the
|
||||
// characteristics/performance from when an ObjectMonitor
|
||||
// "responsible" thread used to issue timed parks.
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval((jlong)1);
|
||||
}
|
||||
::WaitOnAddress(&_Event, &v, sizeof(_Event), INFINITE);
|
||||
delete phri; // if it is null, harmless
|
||||
}
|
||||
} else {
|
||||
// Do this the hard way by blocking ...
|
||||
// TODO: consider a brief spin here, gated on the success of recent
|
||||
// spin attempts by this thread.
|
||||
while (_Event < 0) {
|
||||
// The following code is only here to maintain the
|
||||
// characteristics/performance from when an ObjectMonitor
|
||||
// "responsible" thread used to issue timed parks.
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval((jlong)1);
|
||||
}
|
||||
DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);
|
||||
delete phri; // if it is null, harmless
|
||||
assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
||||
assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", rv);
|
||||
}
|
||||
DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);
|
||||
delete phri; // if it is null, harmless
|
||||
assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
||||
assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", rv);
|
||||
}
|
||||
|
||||
// Usually we'll find _Event == 0 at this point, but as
|
||||
@@ -5721,7 +5751,9 @@ void PlatformEvent::park() {
|
||||
}
|
||||
|
||||
void PlatformEvent::unpark() {
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
if (!UseModernSynchAPI) {
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
}
|
||||
|
||||
// Transitions for _Event:
|
||||
// 0 => 1 : just return
|
||||
@@ -5737,9 +5769,14 @@ void PlatformEvent::unpark() {
|
||||
// from the first park() call after an unpark() call which will help
|
||||
// shake out uses of park() and unpark() without condition variables.
|
||||
|
||||
if (Atomic::xchg(&_Event, 1) >= 0) return;
|
||||
|
||||
::SetEvent(_ParkHandle);
|
||||
if (UseModernSynchAPI) {
|
||||
if (Atomic::xchg(&_Event, 1) >= 0) return;
|
||||
// Changed from -1 to 1; the target thread's WaitOnAddress() must return now
|
||||
::WakeByAddressAll((PVOID) &_Event);
|
||||
} else {
|
||||
if (Atomic::xchg(&_Event, 1) >= 0) return;
|
||||
::SetEvent(_ParkHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,8 +41,10 @@ class PlatformEvent : public CHeapObj<mtSynchronizer> {
|
||||
public:
|
||||
PlatformEvent() {
|
||||
_Event = 0 ;
|
||||
_ParkHandle = CreateEvent (nullptr, false, false, nullptr) ;
|
||||
guarantee (_ParkHandle != nullptr, "invariant") ;
|
||||
if (!UseModernSynchAPI) {
|
||||
_ParkHandle = CreateEvent (nullptr, false, false, nullptr) ;
|
||||
guarantee (_ParkHandle != nullptr, "invariant") ;
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise caution using reset() and fired() - they may require MEMBARs
|
||||
|
||||
Reference in New Issue
Block a user