-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[WIP] Fix the infinite cycle in Lazy Vals #2276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Reported by Andrzej Plutecki in https://groups.google.com/forum/#!topic/dotty-internals/3LMNItLQw-A I haven't seen this happen in practice in hours and hours of benchmarking, but this is indeed a formal bug.
@baszo please review. |
This will not fix @the problem. Because when other thread will set flag to 3 function STATE(cur, ord) that you used with variable cur will be still set to old state in such solution it is needed to reassure and use get function to get new state |
Long time since I wrote this code. Forgot that `State` doesn't read the state.
@baszo, nice catch! it has been long time since I have written this code, so I forgot that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still there is a problem. Last thing to make it working is a little change with setFlag function.
if (STATE(cur, ord) == 1) retry = CAS(t, offset, cur, v, ord)
just remove 'retry ='
Because while 2 thread will use CAS simultaneously one will set 1 to 2 and other 1 to 3. First win and with new update if statement will pass and call wait. In thread that initialized value CAS failed and retry will be set to false and then notifyAll will never be called
@baszo, I'm not sure if I understood you.
If I understood the case you are describing, thread A that succeeds change flag 1 -> 2, and starts syncrhonization. By the time it syncrhonized we know that thread B cannot successfully change 1 -> 3, as the change 1 -> 2 has been passed. This means that the thread B will in any case perform
We have to cases to consider here, either thread A is faster to grab the lock, or thread B is faster to grab the lock. If thread A is faster to grab the lock, it will be woken by notify call when thread B invokes it. Is there something I'm missing? |
BTW: While I still don't see the issue you are describing, solution that you are proposing will lead to infitine recursion in absence of contention. The (state == 1) state has to modify retry, because (state == 2) may never be reached. |
While we at it, I think it's worth to refactor the LazyVals module and document the assumptions in it. Marked WIP for this reason. |
There is 3 case. |
@baszo, are you able to reproduce the issue? what hardware are you using? |
I used to reproduce this problem this code: import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._
object A {
lazy val base: Int = 42
lazy val start = B.step
}
object B {
lazy val step: Int = A.base
}
object ProblemScenario {
def run = {
val result = Future.sequence(Seq(
Future { A.start }, // (1)
Future { B.step } // (2)
))
Await.result(result, 1.minute)
}
} |
Ok i understand what you meant. Solution i mentioned will work and solve the problem but always will call notifyAll so it is inefficient. But do you understand the problem or should i try to describe it better? I can create some call stack of methods to show this particular case. |
I though that through and I think the problem is as I mentioned in SetFlag function. When state == 1 it will try to use CAS and i think it should be because when CAS will fail (that means other thread changed state) it should not quit loop but try again, to get changed state and redo operation of setting new state |
@DarkDimius - this branch is on the dotty repo and not your own fork / staging. For the releases, I'd like to remove it as soon as possible. If you have too much on your plate, I'll push it to staging and re-open the from the correct downstream. |
Sounds good! |
Apply patch suggested in scala#2276
OK, I convinced myself the bugs discussed here are fixed, which makes me rest easier. Looking again at @baszo's scenario there's a typo I think, but otherwise this does describe the bug in
|
Reported by Andrzej Plutecki(@baszo) in https://groups.google.com/forum/#!topic/dotty-internals/3LMNItLQw-A
I haven't seen this happen in practice in hours and hours of benchmarking, but this is indeed a formal bug.