I'm uncertain about PSI caching rules and would love some help here.
A user reported a dead-lock at https://github.com/jansorg/BashSupport/issues/467 .
Basically this is the UI thread waiting for a write action which waits for read actions to finish. The two active read actions dead-lock one another. The lock is caused by a synchronized block in an instance of a PSI class. The block guards lazy-initialized data. One read action is updating stub data and waits for the custom monitor and the other action has acquired the monitor and waits for the stub index.
Two threads access the PSI concurrently (wrapped in read actions): 1) is running the general highlighting and 2) is running a local inspection.
My lazy-init synchronized code is at https://github.com/jansorg/BashSupport/blob/idea-162.x/src/com/ansorgit/plugins/bash/lang/psi/impl/vars/BashVarDefImpl.java#L104 .
I know about subtreeChanged() and the general rules at http://www.jetbrains.org/intellij/sdk/docs/basics/architectural_overview/general_threading_rules.html .
What is the recommended way to do lazy-init in PSI classes?
IntelliJ seems to do this without synchronization. This is not thread-safe and PSI seems to be used concurrently. Are the two examples below correct?
For example https://github.com/JetBrains/intellij-community/blob/9a0a04451e2332ff6a94f17a441c2a4f41ae83b5/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java or https://github.com/JetBrains/intellij-community/blob/accf7523f985547336ed2c0f068c0132f6dcf786/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java .
Thanks a lot!