aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/concurrent/RefCountedMultisetKeyedLocker.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/concurrent/StripedKeyedLocker.java50
-rw-r--r--src/test/java/com/google/devtools/build/lib/concurrent/KeyedLockerTest.java2
-rw-r--r--src/test/java/com/google/devtools/build/lib/concurrent/StripedKeyedLockerTest.java26
4 files changed, 77 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/concurrent/RefCountedMultisetKeyedLocker.java b/src/main/java/com/google/devtools/build/lib/concurrent/RefCountedMultisetKeyedLocker.java
index 52109ad543..64d530e617 100644
--- a/src/main/java/com/google/devtools/build/lib/concurrent/RefCountedMultisetKeyedLocker.java
+++ b/src/main/java/com/google/devtools/build/lib/concurrent/RefCountedMultisetKeyedLocker.java
@@ -60,11 +60,6 @@ public class RefCountedMultisetKeyedLocker<K> implements KeyedLocker<K> {
+ "AutoUnlocker instance", key);
throw new IllegalUnlockException(msg);
}
- if (!lock.isHeldByCurrentThread()) {
- String msg = String.format("For key %s, the calling thread to 'close' must be the one "
- + "that acquired the AutoUnlocker", key);
- throw new IllegalUnlockException(msg);
- }
try {
Lock waitersLock = waitersLocks.get(key);
try {
diff --git a/src/main/java/com/google/devtools/build/lib/concurrent/StripedKeyedLocker.java b/src/main/java/com/google/devtools/build/lib/concurrent/StripedKeyedLocker.java
new file mode 100644
index 0000000000..505ea6c195
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/concurrent/StripedKeyedLocker.java
@@ -0,0 +1,50 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.concurrent;
+
+import com.google.common.util.concurrent.Striped;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * An implementation of {@link KeyedLocker} backed by a {@link Striped}.
+ */
+public class StripedKeyedLocker<K> implements KeyedLocker<K> {
+
+ private final Striped<Lock> locks;
+
+ public StripedKeyedLocker(int stripes) {
+ locks = Striped.lock(stripes);
+ }
+
+ @Override
+ public AutoUnlocker lock(final K key) {
+ final Lock lock = locks.get(key);
+ lock.lock();
+ return new AutoUnlocker() {
+ private final AtomicBoolean closeCalled = new AtomicBoolean(false);
+
+ @Override
+ public void close() {
+ if (closeCalled.getAndSet(true)) {
+ String msg = String.format("For key %s, 'close' can be called at most once per "
+ + "AutoUnlocker instance", key);
+ throw new IllegalUnlockException(msg);
+ }
+ lock.unlock();
+ }
+ };
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/concurrent/KeyedLockerTest.java b/src/test/java/com/google/devtools/build/lib/concurrent/KeyedLockerTest.java
index 1549a548ac..b87983a3d2 100644
--- a/src/test/java/com/google/devtools/build/lib/concurrent/KeyedLockerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/concurrent/KeyedLockerTest.java
@@ -203,7 +203,7 @@ public abstract class KeyedLockerTest {
try {
Preconditions.checkNotNull(unlockerRef.get()).close();
fail();
- } catch (IllegalUnlockException expected) {
+ } catch (IllegalMonitorStateException expected) {
runnable2Executed.set(true);
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/concurrent/StripedKeyedLockerTest.java b/src/test/java/com/google/devtools/build/lib/concurrent/StripedKeyedLockerTest.java
new file mode 100644
index 0000000000..5ae0b28c3b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/concurrent/StripedKeyedLockerTest.java
@@ -0,0 +1,26 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.concurrent;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link StripedKeyedLocker}. */
+@RunWith(JUnit4.class)
+public class StripedKeyedLockerTest extends KeyedLockerTest {
+ @Override
+ protected KeyedLocker<String> makeFreshLocker() {
+ return new StripedKeyedLocker<>(17);
+ }
+}