mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-17 04:32:04 +01:00
reactor: have synchronized block include peeking at scheduled actions
If we do not peek at the scheduled actions in the reactors synchronized block, then there is a kind of lost-update problem. While Ractor.schedule() will call wakeup() on the selector, a thread could have already determined the value of selectWait, while being blocked at the start of the synchronized reactor section. Once it is able to enter the section, it will use an outdated selectWait value. This leads to scheduled actions not being executed on time. Thanks to Eng ChongMeng for reporting this and suggesting the fix.
This commit is contained in:
parent
05c920ab56
commit
b510d373b5
1 changed files with 16 additions and 16 deletions
|
@ -204,25 +204,25 @@ public class SmackReactor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduledAction nextScheduledAction = scheduledActions.peek();
|
|
||||||
|
|
||||||
long selectWait;
|
|
||||||
if (nextScheduledAction == null) {
|
|
||||||
// There is no next scheduled action, wait indefinitely in select() or until another thread invokes
|
|
||||||
// selector.wakeup().
|
|
||||||
selectWait = 0;
|
|
||||||
} else {
|
|
||||||
selectWait = nextScheduledAction.getTimeToDueMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectWait < 0) {
|
|
||||||
// A scheduled action was just released and became ready to execute.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int newSelectedKeysCount = 0;
|
int newSelectedKeysCount = 0;
|
||||||
List<SelectionKey> selectedKeys;
|
List<SelectionKey> selectedKeys;
|
||||||
synchronized (selector) {
|
synchronized (selector) {
|
||||||
|
ScheduledAction nextScheduledAction = scheduledActions.peek();
|
||||||
|
|
||||||
|
long selectWait;
|
||||||
|
if (nextScheduledAction == null) {
|
||||||
|
// There is no next scheduled action, wait indefinitely in select() or until another thread invokes
|
||||||
|
// selector.wakeup().
|
||||||
|
selectWait = 0;
|
||||||
|
} else {
|
||||||
|
selectWait = nextScheduledAction.getTimeToDueMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectWait < 0) {
|
||||||
|
// A scheduled action was just released and became ready to execute.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Before we call select, we handle the pending the interest Ops. This will not block since no other
|
// Before we call select, we handle the pending the interest Ops. This will not block since no other
|
||||||
// thread is currently in select() at this time.
|
// thread is currently in select() at this time.
|
||||||
// Note: This was put deliberately before the registration lock. It may cause more synchronization but
|
// Note: This was put deliberately before the registration lock. It may cause more synchronization but
|
||||||
|
|
Loading…
Reference in a new issue