aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java
diff options
context:
space:
mode:
authorGravatar Nathan Harmata <nharmata@google.com>2015-08-10 16:46:25 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2015-08-11 07:51:54 +0000
commit12b39567bf3743b99dc1d943b772f2cd57124e8e (patch)
tree667d62c226e53e18ade10c5a6d0a6260c4e7d6c4 /src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java
parent1b5c327ea2d897b344ecb1cb897bcb8eee0a5774 (diff)
Add comments about subtle benign race in PathFragment#hashCode.
-- MOS_MIGRATED_REVID=100285918
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java b/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java
index d14f781703..e8fdf36510 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/PathFragment.java
@@ -641,6 +641,22 @@ public final class PathFragment implements Comparable<PathFragment>, Serializabl
@Override
public int hashCode() {
+ // We use the hash code caching strategy employed by java.lang.String. There are three subtle
+ // things going on here:
+ //
+ // (1) We use a value of 0 to indicate that the hash code hasn't been computed and cached yet.
+ // Yes, this means that if the hash code is really 0 then we will "recompute" it each time. But
+ // this isn't a problem in practice since a hash code of 0 is rare.
+ //
+ // (2) Since we have no synchronization, multiple threads can race here thinking there are the
+ // first one to compute and cache the hash code.
+ //
+ // (3) Moreover, since 'hashCode' is non-volatile, the cached hash code value written from one
+ // thread may not be visible by another.
+ //
+ // All three of these issues are benign from a correctness perspective; in the end we have no
+ // overhead from synchronization, at the cost of potentially computing the hash code more than
+ // once.
int h = hashCode;
if (h == 0) {
h = isAbsolute ? 1 : 0;