Fix possible lost signal in ControlledRealTimeReopenThread#15830
Fix possible lost signal in ControlledRealTimeReopenThread#15830dweiss merged 5 commits intoapache:mainfrom
ControlledRealTimeReopenThread#15830Conversation
ControlledRealTimeReopenThreadControlledRealTimeReopenThread
|
This PR has not had activity in the past 2 weeks, labeling it as stale. If the PR is waiting for review, notify the dev@lucene.apache.org list. Thank you for your contribution! |
dweiss
left a comment
There was a problem hiding this comment.
I'm not that familiar with this code but this change looks ok. Thanks for tackling the difficult concurrency stuff.
I feel tempted to make synchronization explicit (instead of method keyword) consistently. Makes reasoning a bit easier (to me). What do you think?
|
I allowed myself to add an explicit monitor and change the parameters to an explicit Duration. I think it's clearer and the class is experimental so no problem there. Let me know if this is ok. |
|
Not synchronizing on the instance itself is a good practice, so it's fine. |
|
This is clearly marked as an experimental class so I don't think this matters. People will have to adjust (and then at least they'll know what the time unit passed to this constructor is - the fraction-of-a-second-double is really strange, at least to me). |
Condition.signal/awaitwas used to wake up the background thread to reload data. Since the background thread isn't owning the condition's lock at all times, notification can be lost. Specifically, if a new waiter arrives while doingmaybeRefreshBlocking()and before it obtains the lock again, the thread will go to sleep, instead of refreshing again. Similarly, the thread won't terminate ifclose()is called during this window. The issue is pronounced if minTime is 0 and maxTime is high. Owning the lock all the time is not a solution, because it would unnecessarily block all waiters, even if they are not interested in the generation being loaded.This PR replaces this notification with a semaphore. The semaphore collects permits, and the background thread tries to acquire a permit with a timeout as a way of sleeping. Releasing a permit serves as the signal. This way no notification is lost.
There's another wait-notify construct in this class, but that one is correct. The waiter owns the lock all the time, and the write to
searchingGenis done while holding the same monitor.Other changes included in this PR:
run()method), now it's simple steps: loop until finished, in each iteration determine sleep time, if >0, sleep, else refresh.refreshStartGento the listener class, it's used only thereThreaditself, not a utility. The user has to run it. And more...