mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
removed obsolete concurrency primitives
This commit is contained in:
@@ -48,14 +48,13 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class RefManagerImpl extends RefManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.reference.RefManager");
|
||||
@@ -80,7 +79,7 @@ public class RefManagerImpl extends RefManager {
|
||||
private final Map<Key, RefManagerExtension> myExtensions = new HashMap<Key, RefManagerExtension>();
|
||||
private final HashMap<Language, RefManagerExtension> myLanguageExtensions = new HashMap<Language, RefManagerExtension>();
|
||||
|
||||
private final JBReentrantReadWriteLock myLock = LockFactory.createReadWriteLock();
|
||||
private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();
|
||||
|
||||
public RefManagerImpl(Project project, AnalysisScope scope, GlobalInspectionContextImpl context) {
|
||||
myDeclarationsFound = false;
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency.readwrite;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AbstractWaiter implements Runnable {
|
||||
|
||||
private boolean myFinishedFlag;
|
||||
|
||||
public void setFinished(boolean aFinishedFlag) {
|
||||
myFinishedFlag = aFinishedFlag;
|
||||
}
|
||||
|
||||
private boolean finished() {
|
||||
return myFinishedFlag;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!finished()) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForCompletion() {
|
||||
waitForCompletion(0);
|
||||
}
|
||||
|
||||
public void waitForCompletion(long aTimeout) {
|
||||
try {
|
||||
final Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(this);
|
||||
if (aTimeout > 0) future.get(aTimeout, TimeUnit.MILLISECONDS);
|
||||
else future.get();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency.readwrite;
|
||||
|
||||
public interface ActiveRunnable {
|
||||
|
||||
Object run() throws Throwable;
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency.readwrite;
|
||||
|
||||
public abstract class ActiveRunnableWrapper implements Runnable {
|
||||
|
||||
private Object myResult;
|
||||
|
||||
private Throwable myException;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
myResult = doRun();
|
||||
}
|
||||
catch (Throwable aThrowable) {
|
||||
myException = aThrowable;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getResult() {
|
||||
return myResult;
|
||||
}
|
||||
|
||||
private Throwable getException() {
|
||||
return myException;
|
||||
}
|
||||
|
||||
private boolean hasException() {
|
||||
return null != getException();
|
||||
}
|
||||
|
||||
public void throwException() throws Throwable {
|
||||
if (hasException()) {
|
||||
throw getException();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Object doRun() throws Throwable;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency.readwrite;
|
||||
|
||||
import com.intellij.openapi.command.CommandEvent;
|
||||
import com.intellij.openapi.command.CommandListener;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
|
||||
public class CommandWaiter extends AbstractWaiter implements CommandListener {
|
||||
|
||||
private final Runnable myCommandRunnable;
|
||||
|
||||
public CommandWaiter(Runnable aCommandRunnable) {
|
||||
myCommandRunnable = aCommandRunnable;
|
||||
|
||||
setFinished(false);
|
||||
CommandProcessor.getInstance().addCommandListener(this);
|
||||
}
|
||||
|
||||
public void beforeCommandFinished(CommandEvent event) {
|
||||
}
|
||||
|
||||
public void commandFinished(CommandEvent event) {
|
||||
if (event.getCommand() == myCommandRunnable) {
|
||||
CommandProcessor.getInstance().removeCommandListener(this);
|
||||
setFinished(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void commandStarted(CommandEvent event) {
|
||||
}
|
||||
|
||||
public void undoTransparentActionStarted() {
|
||||
}
|
||||
|
||||
public void undoTransparentActionFinished() {
|
||||
}
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency.readwrite;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationListener;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
|
||||
public class WriteActionWaiter extends AbstractWaiter implements ApplicationListener {
|
||||
|
||||
private final Runnable myActionRunnable;
|
||||
|
||||
public WriteActionWaiter(Runnable aActionRunnable) {
|
||||
myActionRunnable = aActionRunnable;
|
||||
|
||||
setFinished(false);
|
||||
ApplicationManager.getApplication().addApplicationListener(this);
|
||||
}
|
||||
|
||||
public void writeActionFinished(Object aRunnable) {
|
||||
if (aRunnable == myActionRunnable) {
|
||||
setFinished(true);
|
||||
|
||||
ApplicationManager.getApplication().removeApplicationListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void applicationExiting() {
|
||||
}
|
||||
|
||||
public void beforeWriteActionStart(Object action) {
|
||||
}
|
||||
|
||||
public boolean canExitApplication() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void writeActionStarted(Object action) {
|
||||
}
|
||||
|
||||
public void applicationActivated(IdeFrame ideFrame) {
|
||||
}
|
||||
|
||||
public void applicationDeactivated(IdeFrame ideFrame) {
|
||||
}
|
||||
}
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency.readwrite;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
public abstract class WriteActionWorker extends ActiveRunnableWrapper {
|
||||
|
||||
private void start() {
|
||||
WriteActionWaiter waiter = new WriteActionWaiter(this);
|
||||
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
ApplicationManager.getApplication().runWriteAction(WriteActionWorker.this);
|
||||
} else {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(WriteActionWorker.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
waiter.waitForCompletion();
|
||||
}
|
||||
|
||||
public static Object run(final ActiveRunnable aActiveRunnable) throws Throwable {
|
||||
WriteActionWorker worker = new WriteActionWorker() {
|
||||
public Object doRun() throws Throwable {
|
||||
return aActiveRunnable.run();
|
||||
}
|
||||
};
|
||||
|
||||
worker.start();
|
||||
worker.throwException();
|
||||
|
||||
return worker.getResult();
|
||||
}
|
||||
|
||||
private static class CommandWrapper extends ActiveRunnableWrapper {
|
||||
|
||||
private final ActiveRunnable myWriteActionRunnable;
|
||||
|
||||
public CommandWrapper(ActiveRunnable aWriteActionRunnable) {
|
||||
myWriteActionRunnable = aWriteActionRunnable;
|
||||
}
|
||||
|
||||
public Object doRun() throws Throwable {
|
||||
return WriteActionWorker.run(myWriteActionRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object runInCommand(final Project project, final ActiveRunnable aActiveRunnable, final String aCommandName) throws Throwable {
|
||||
final CommandWrapper commandWrapper = new CommandWrapper(aActiveRunnable);
|
||||
|
||||
CommandWaiter commandWaiter = new CommandWaiter(commandWrapper);
|
||||
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
CommandProcessor.getInstance().executeCommand(project, commandWrapper, aCommandName, null);
|
||||
} else {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
CommandProcessor.getInstance().executeCommand(project, commandWrapper, aCommandName, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
commandWaiter.waitForCompletion();
|
||||
commandWrapper.throwException();
|
||||
|
||||
return commandWrapper.getResult();
|
||||
}
|
||||
}
|
||||
+13
-15
@@ -30,9 +30,6 @@ import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.concurrency.JBLock;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import com.intellij.util.containers.IntArrayList;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
@@ -46,6 +43,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@SuppressWarnings({"PointlessArithmeticExpression", "HardCodedStringLiteral"})
|
||||
public class FSRecords implements Forceable {
|
||||
@@ -87,8 +85,8 @@ public class FSRecords implements Forceable {
|
||||
|
||||
private static final String CHILDREN_ATT = "FsRecords.DIRECTORY_CHILDREN";
|
||||
|
||||
private static final JBLock r;
|
||||
private static final JBLock w;
|
||||
private static final ReentrantReadWriteLock.ReadLock r;
|
||||
private static final ReentrantReadWriteLock.WriteLock w;
|
||||
|
||||
private static volatile int ourLocalModificationCount = 0;
|
||||
private static volatile boolean ourIsDisposed;
|
||||
@@ -100,12 +98,12 @@ public class FSRecords implements Forceable {
|
||||
//noinspection ConstantConditions
|
||||
assert HEADER_SIZE <= RECORD_SIZE;
|
||||
|
||||
JBReentrantReadWriteLock lock = LockFactory.createReadWriteLock();
|
||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
r = lock.readLock();
|
||||
w = lock.writeLock();
|
||||
}
|
||||
|
||||
private static class DbConnection {
|
||||
static class DbConnection {
|
||||
private static boolean ourInitialized;
|
||||
private static final TObjectIntHashMap<String> myAttributeIds = new TObjectIntHashMap<String>();
|
||||
|
||||
@@ -411,7 +409,7 @@ public class FSRecords implements Forceable {
|
||||
myRecords.putInt(HEADER_CONNECTION_STATUS_OFFSET, SAFELY_CLOSED_MAGIC);
|
||||
}
|
||||
|
||||
public static void cleanRecord(final int id) {
|
||||
static void cleanRecord(int id) {
|
||||
myRecords.put(id * RECORD_SIZE, ZEROES, 0, RECORD_SIZE);
|
||||
}
|
||||
|
||||
@@ -615,7 +613,7 @@ public class FSRecords implements Forceable {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addToFreeRecordsList(int id) {
|
||||
static void addToFreeRecordsList(int id) {
|
||||
DbConnection.addFreeRecord(id);
|
||||
setFlags(id, FREE_RECORD_FLAG, false);
|
||||
}
|
||||
@@ -1409,14 +1407,14 @@ public class FSRecords implements Forceable {
|
||||
final IntArrayList validAttributeIds) {
|
||||
int parentId = getParent(id);
|
||||
assert parentId >= 0 && parentId < recordCount;
|
||||
if (parentId > 0) {
|
||||
final int parentFlags = getFlags(parentId);
|
||||
assert (parentFlags & FREE_RECORD_FLAG) == 0;
|
||||
assert (parentFlags & PersistentFS.IS_DIRECTORY_FLAG) != 0;
|
||||
if (parentId > 0 && getParent(parentId) > 0) {
|
||||
int parentFlags = getFlags(parentId);
|
||||
assert (parentFlags & FREE_RECORD_FLAG) == 0 : parentId + ": "+Integer.toHexString(parentFlags);
|
||||
assert (parentFlags & PersistentFS.IS_DIRECTORY_FLAG) != 0 : parentId + ": "+Integer.toHexString(parentFlags);
|
||||
}
|
||||
|
||||
String name = getName(id);
|
||||
LOG.assertTrue(parentId == 0 || name.length() > 0, "File with empty name found under " + getName(parentId) + ", id=" + id);
|
||||
LOG.assertTrue(parentId == 0 || !name.isEmpty(), "File with empty name found under " + getName(parentId) + ", id=" + id);
|
||||
|
||||
checkContentsStorageSanity(id);
|
||||
checkAttributesStorageSanity(id, usedAttributeRecordIds, validAttributeIds);
|
||||
@@ -1460,7 +1458,7 @@ public class FSRecords implements Forceable {
|
||||
assert !usedAttributeRecordIds.contains(attDataRecordId);
|
||||
usedAttributeRecordIds.add(attDataRecordId);
|
||||
if (!validAttributeIds.contains(attId)) {
|
||||
assert getNames().valueOf(attId).length() > 0;
|
||||
assert !getNames().valueOf(attId).isEmpty();
|
||||
validAttributeIds.add(attId);
|
||||
}
|
||||
getAttributesStorage().checkSanity(attDataRecordId);
|
||||
|
||||
@@ -28,8 +28,6 @@ import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -38,6 +36,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
@@ -46,7 +45,7 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.PathMacrosImpl");
|
||||
private final Map<String, String> myLegacyMacros = new HashMap<String, String>();
|
||||
private final Map<String, String> myMacros = new HashMap<String, String>();
|
||||
private final JBReentrantReadWriteLock myLock = LockFactory.createReadWriteLock();
|
||||
private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();
|
||||
private final List<String> myIgnoredMacros = ContainerUtil.createEmptyCOWList();
|
||||
|
||||
@NonNls
|
||||
|
||||
@@ -74,13 +74,6 @@ public class Patches {
|
||||
*/
|
||||
public static final boolean APPLE_BUG_ID_3716835 = SystemInfo.isMac && !SystemInfo.isJavaVersionAtLeast("1.4.2.5");
|
||||
|
||||
/**
|
||||
* Use of JDK1.5 ReentrantReadWriteLock API eventually leads to JVM lock-up or core dump crashes.
|
||||
* With this flag true, API is wrapped with alternative implementation via early days Doug Lea's API.
|
||||
* @see com.intellij.util.concurrency.LockFactory
|
||||
*/
|
||||
public static final boolean APPLE_BUG_ID_5359442 = SystemInfo.isMac && (!SystemInfo.isMacOSLeopard || !SystemInfo.isJavaVersionAtLeast("1.5.0_16"));
|
||||
|
||||
/**
|
||||
* Lion eAWT FullScreen mode leads to visual artifacts.
|
||||
*/
|
||||
|
||||
@@ -16,17 +16,15 @@
|
||||
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
import com.intellij.util.concurrency.JBLock;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public abstract class FieldCache<T, Owner,AccessorParameter,Parameter> {
|
||||
private static final RecursionGuard ourGuard = RecursionManager.createGuard("fieldCache");
|
||||
private final JBLock r;
|
||||
private final JBLock w;
|
||||
private final ReentrantReadWriteLock.ReadLock r;
|
||||
private final ReentrantReadWriteLock.WriteLock w;
|
||||
|
||||
protected FieldCache() {
|
||||
JBReentrantReadWriteLock ourLock = LockFactory.createReadWriteLock();
|
||||
ReentrantReadWriteLock ourLock = new ReentrantReadWriteLock();
|
||||
r = ourLock.readLock();
|
||||
w = ourLock.writeLock();
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
public class DefaultLockAdapter implements JBLock {
|
||||
private final Lock myAdaptee;
|
||||
|
||||
public DefaultLockAdapter(final Lock adaptee) {
|
||||
myAdaptee = adaptee;
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
myAdaptee.lock();
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
myAdaptee.unlock();
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class DefaultReentrantReadWriteLockAdapter implements JBReentrantReadWriteLock {
|
||||
private final DefaultLockAdapter myReadLock;
|
||||
private final DefaultLockAdapter myWriteLock;
|
||||
private final ReentrantReadWriteLock myAdaptee;
|
||||
|
||||
public DefaultReentrantReadWriteLockAdapter() {
|
||||
myAdaptee = new ReentrantReadWriteLock();
|
||||
myReadLock = new DefaultLockAdapter(myAdaptee.readLock());
|
||||
myWriteLock = new DefaultLockAdapter(myAdaptee.writeLock());
|
||||
}
|
||||
|
||||
public JBLock readLock() {
|
||||
return myReadLock;
|
||||
}
|
||||
|
||||
public JBLock writeLock() {
|
||||
return myWriteLock;
|
||||
}
|
||||
|
||||
public boolean isWriteLockedByCurrentThread() {
|
||||
return myAdaptee.isWriteLockedByCurrentThread();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
public interface JBLock {
|
||||
void lock();
|
||||
void unlock();
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
/**
|
||||
* @see LockFactory
|
||||
*/
|
||||
public interface JBReentrantReadWriteLock {
|
||||
JBLock readLock();
|
||||
JBLock writeLock();
|
||||
boolean isWriteLockedByCurrentThread();
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import com.intellij.Patches;
|
||||
|
||||
public class LockFactory {
|
||||
private LockFactory() {}
|
||||
|
||||
public static JBReentrantReadWriteLock createReadWriteLock() {
|
||||
if (Patches.APPLE_BUG_ID_5359442) {
|
||||
return new SynchronizedBasedReentrantReadWriteLock();
|
||||
}
|
||||
else {
|
||||
return new DefaultReentrantReadWriteLockAdapter();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency;
|
||||
|
||||
/**
|
||||
* ReadWriteLocks maintain a pair of associated locks.
|
||||
* The readLock may be held simultanously by multiple
|
||||
* reader threads, so long as there are no writers. The writeLock
|
||||
* is exclusive. ReadWrite locks are generally preferable to
|
||||
* plain Sync locks or synchronized methods in cases where:
|
||||
* <ul>
|
||||
* <li> The methods in a class can be cleanly separated into
|
||||
* those that only access (read) data vs those that
|
||||
* modify (write).
|
||||
* <li> Target applications generally have more readers than writers.
|
||||
* <li> The methods are relatively time-consuming (as a rough
|
||||
* rule of thumb, exceed more than a hundred instructions), so it
|
||||
* pays to introduce a bit more overhead associated with
|
||||
* ReadWrite locks compared to simple synchronized methods etc
|
||||
* in order to allow concurrency among reader threads.
|
||||
*
|
||||
* </ul>
|
||||
* Different implementation classes differ in policies surrounding
|
||||
* which threads to prefer when there is
|
||||
* contention. By far, the most commonly useful policy is
|
||||
* WriterPreferenceReadWriteLock. The other implementations
|
||||
* are targeted for less common, niche applications.
|
||||
*<p>
|
||||
* Standard usage:
|
||||
* <pre>
|
||||
* class X {
|
||||
* ReadWriteLock rw;
|
||||
* // ...
|
||||
*
|
||||
* public void read() throws InterruptedException {
|
||||
* rw.readLock().acquire();
|
||||
* try {
|
||||
* // ... do the read
|
||||
* }
|
||||
* finally {
|
||||
* rw.readlock().release()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*
|
||||
* public void write() throws InterruptedException {
|
||||
* rw.writeLock().acquire();
|
||||
* try {
|
||||
* // ... do the write
|
||||
* }
|
||||
* finally {
|
||||
* rw.writelock().release()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @see Sync
|
||||
* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
|
||||
|
||||
**/
|
||||
|
||||
public interface ReadWriteLock {
|
||||
/** get the readLock **/
|
||||
Sync readLock();
|
||||
|
||||
/** get the writeLock **/
|
||||
Sync writeLock();
|
||||
}
|
||||
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency;
|
||||
|
||||
import gnu.trove.TIntArrayList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A writer-preference ReadWriteLock that allows both readers and
|
||||
* writers to reacquire
|
||||
* read or write locks in the style of a ReentrantLock.
|
||||
* Readers are not allowed until all write locks held by
|
||||
* the writing thread have been released.
|
||||
* Among other applications, reentrancy can be useful when
|
||||
* write locks are held during calls or callbacks to methods that perform
|
||||
* reads under read locks.
|
||||
* <p>
|
||||
* <b>Sample usage</b>. Here is a code sketch showing how to exploit
|
||||
* reentrancy to perform lock downgrading after updating a cache:
|
||||
* <pre>
|
||||
* class CachedData {
|
||||
* Object data;
|
||||
* volatile boolean cacheValid;
|
||||
* ReentrantWriterPreferenceReadWriteLock rwl = ...
|
||||
*
|
||||
* void processCachedData() {
|
||||
* rwl.readLock().acquire();
|
||||
* if (!cacheValid) {
|
||||
*
|
||||
* // upgrade lock:
|
||||
* rwl.readLock().release(); // must release first to obtain writelock
|
||||
* rwl.writeLock().acquire();
|
||||
* if (!cacheValid) { // recheck
|
||||
* data = ...
|
||||
* cacheValid = true;
|
||||
* }
|
||||
* // downgrade lock
|
||||
* rwl.readLock().acquire(); // reacquire read without giving up lock
|
||||
* rwl.writeLock().release(); // release write, still hold read
|
||||
* }
|
||||
*
|
||||
* use(data);
|
||||
* rwl.readLock().release();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
|
||||
**/
|
||||
|
||||
public class ReentrantWriterPreferenceReadWriteLock extends WriterPreferenceReadWriteLock {
|
||||
|
||||
/** Number of acquires on write lock by activeWriter_ thread **/
|
||||
private long writeHolds_ = 0;
|
||||
|
||||
private final ThreadToCountMap readers_ = new ThreadToCountMap();
|
||||
|
||||
private final ThreadLocal<Boolean> hasReadLock = new ThreadLocal<Boolean>() {
|
||||
@Override
|
||||
protected Boolean initialValue() {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
private final ThreadLocal<Boolean> hasWriteLock = new ThreadLocal<Boolean>() {
|
||||
@Override
|
||||
protected Boolean initialValue() {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
public boolean isReadLockAcquired() {
|
||||
return hasReadLock.get();
|
||||
}
|
||||
|
||||
public boolean isWriteLockAcquired() {
|
||||
return hasWriteLock.get();
|
||||
}
|
||||
|
||||
public synchronized boolean isReadLockAcquired(Thread thread){
|
||||
return readers_.get(thread) > 0;
|
||||
}
|
||||
|
||||
public synchronized boolean isWriteLockAcquired(Thread thread){
|
||||
return activeWriter_ == thread;
|
||||
}
|
||||
|
||||
protected boolean allowReader() {
|
||||
// [Valentin] Changed policy so that readers are allowed while there are waiting writers
|
||||
// [cdr]: No more!
|
||||
return (activeWriter_ == null && waitingWriters_ == 0) ||
|
||||
activeWriter_ == Thread.currentThread();
|
||||
}
|
||||
|
||||
protected synchronized boolean startRead() {
|
||||
Thread t = Thread.currentThread();
|
||||
int c = readers_.get(t);
|
||||
if (c > 0) { // already held -- just increment hold count
|
||||
readers_.put(t, c + 1);
|
||||
++activeReaders_;
|
||||
return true;
|
||||
}
|
||||
else if (allowReader()) {
|
||||
hasReadLock.set(true);
|
||||
readers_.put(t, 1);
|
||||
++activeReaders_;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
protected synchronized boolean startWrite() {
|
||||
if (activeWriter_ == Thread.currentThread()) { // already held; re-acquire
|
||||
++writeHolds_;
|
||||
return true;
|
||||
}
|
||||
else if (writeHolds_ == 0) {
|
||||
if (activeReaders_ == 0 ||
|
||||
(readers_.size() == 1 &&
|
||||
readers_.get(Thread.currentThread()) > 0)) {
|
||||
activeWriter_ = Thread.currentThread();
|
||||
hasWriteLock.set(true);
|
||||
writeHolds_ = 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected synchronized Signaller endRead() {
|
||||
--activeReaders_;
|
||||
Thread t = Thread.currentThread();
|
||||
int c = readers_.get(t);
|
||||
if (c != 1) { // more than one hold; decrement count
|
||||
readers_.put(t, c - 1);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
readers_.put(t, 0);
|
||||
hasReadLock.set(false);
|
||||
|
||||
if (writeHolds_ > 0) { // a write lock is still held by current thread
|
||||
return null;
|
||||
}
|
||||
else if (/*activeReaders_ == 0 && */activeReaders_ <= 1 && waitingWriters_ > 0) {
|
||||
// [Valentin] commented out check for activeReaders == 0 - it's incorrect when waiting writer is already a reader!!
|
||||
return writerLock_;
|
||||
}
|
||||
else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized Signaller endWrite() {
|
||||
--writeHolds_;
|
||||
if (writeHolds_ > 0) // still being held
|
||||
return null;
|
||||
else {
|
||||
activeWriter_ = null;
|
||||
hasWriteLock.set(false);
|
||||
if (waitingReaders_ > 0 && allowReader())
|
||||
return readerLock_;
|
||||
else if (waitingWriters_ > 0)
|
||||
return writerLock_;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ThreadToCountMap{
|
||||
private final ArrayList<Thread> myThreads = new ArrayList<Thread>();
|
||||
private final TIntArrayList myCounters = new TIntArrayList();
|
||||
|
||||
private Thread myLastThread = null; // optimization
|
||||
private int myLastCounter;
|
||||
|
||||
public int get(Thread thread){
|
||||
if (thread == myLastThread) return myLastCounter;
|
||||
int index = myThreads.indexOf(thread);
|
||||
int result = index >= 0 ? myCounters.getQuick(index) : 0;
|
||||
myLastThread = thread;
|
||||
myLastCounter = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void put(Thread thread, int count){
|
||||
myLastThread = null;
|
||||
int index = myThreads.indexOf(thread);
|
||||
if (index >= 0){
|
||||
if (count == 0){
|
||||
myThreads.remove(index);
|
||||
myCounters.remove(index);
|
||||
}
|
||||
else{
|
||||
myCounters.setQuick(index, count);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (count != 0){
|
||||
myThreads.add(thread);
|
||||
myCounters.add(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return myThreads.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency;
|
||||
|
||||
/**
|
||||
* Main interface for locks, gates, and conditions.
|
||||
* <p>
|
||||
* Sync objects isolate waiting and notification for particular
|
||||
* logical states, resource availability, events, and the like that are
|
||||
* shared across multiple threads. Use of Syncs sometimes
|
||||
* (but by no means always) adds flexibility and efficiency
|
||||
* compared to the use of plain java monitor methods
|
||||
* and locking, and are sometimes (but by no means always)
|
||||
* simpler to program with.
|
||||
* <p>
|
||||
*
|
||||
* Most Syncs are intended to be used primarily (although
|
||||
* not exclusively) in before/after constructions such as:
|
||||
* <pre>
|
||||
* class X {
|
||||
* Sync gate;
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* try {
|
||||
* gate.acquire(); // block until condition holds
|
||||
* try {
|
||||
* // ... method body
|
||||
* }
|
||||
* finally {
|
||||
* gate.release()
|
||||
* }
|
||||
* }
|
||||
* catch (InterruptedException ex) {
|
||||
* // ... evasive action
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public void m2(Sync cond) { // use supplied condition
|
||||
* try {
|
||||
* if (cond.attempt(10)) { // try the condition for 10 ms
|
||||
* try {
|
||||
* // ... method body
|
||||
* }
|
||||
* finally {
|
||||
* cond.release()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* catch (InterruptedException ex) {
|
||||
* // ... evasive action
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* Syncs may be used in somewhat tedious but more flexible replacements
|
||||
* for built-in Java synchronized blocks. For example:
|
||||
* <pre>
|
||||
* class HandSynched {
|
||||
* private double state_ = 0.0;
|
||||
* private final Sync lock; // use lock type supplied in constructor
|
||||
* public HandSynched(Sync l) { lock = l; }
|
||||
*
|
||||
* public void changeState(double d) {
|
||||
* try {
|
||||
* lock.acquire();
|
||||
* try { state_ = updateFunction(d); }
|
||||
* finally { lock.release(); }
|
||||
* }
|
||||
* catch(InterruptedException ex) { }
|
||||
* }
|
||||
*
|
||||
* public double getState() {
|
||||
* double d = 0.0;
|
||||
* try {
|
||||
* lock.acquire();
|
||||
* try { d = accessFunction(state_); }
|
||||
* finally { lock.release(); }
|
||||
* }
|
||||
* catch(InterruptedException ex){}
|
||||
* return d;
|
||||
* }
|
||||
* private double updateFunction(double d) { ... }
|
||||
* private double accessFunction(double d) { ... }
|
||||
* }
|
||||
* </pre>
|
||||
* If you have a lot of such methods, and they take a common
|
||||
* form, you can standardize this using wrappers. Some of these
|
||||
* wrappers are standardized in LockedExecutor, but you can make others.
|
||||
* For example:
|
||||
* <pre>
|
||||
* class HandSynchedV2 {
|
||||
* private double state_ = 0.0;
|
||||
* private final Sync lock; // use lock type supplied in constructor
|
||||
* public HandSynchedV2(Sync l) { lock = l; }
|
||||
*
|
||||
* protected void runSafely(Runnable r) {
|
||||
* try {
|
||||
* lock.acquire();
|
||||
* try { r.run(); }
|
||||
* finally { lock.release(); }
|
||||
* }
|
||||
* catch (InterruptedException ex) { // propagate without throwing
|
||||
* Thread.currentThread().interrupt();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public void changeState(double d) {
|
||||
* runSafely(new Runnable() {
|
||||
* public void run() { state_ = updateFunction(d); }
|
||||
* });
|
||||
* }
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* One reason to bother with such constructions is to use deadlock-
|
||||
* avoiding back-offs when dealing with locks involving multiple objects.
|
||||
* For example, here is a Cell class that uses attempt to back-off
|
||||
* and retry if two Cells are trying to swap values with each other
|
||||
* at the same time.
|
||||
* <pre>
|
||||
* class Cell {
|
||||
* long value;
|
||||
* Sync lock = ... // some sync implementation class
|
||||
* void swapValue(Cell other) {
|
||||
* for (;;) {
|
||||
* try {
|
||||
* lock.acquire();
|
||||
* try {
|
||||
* if (other.lock.attempt(100)) {
|
||||
* try {
|
||||
* long t = value;
|
||||
* value = other.value;
|
||||
* other.value = t;
|
||||
* return;
|
||||
* }
|
||||
* finally { other.lock.release(); }
|
||||
* }
|
||||
* }
|
||||
* finally { lock.release(); }
|
||||
* }
|
||||
* catch (InterruptedException ex) { return; }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*</pre>
|
||||
* <p>
|
||||
* Here is an even fancier version, that uses lock re-ordering
|
||||
* upon conflict:
|
||||
* <pre>
|
||||
* class Cell {
|
||||
* long value;
|
||||
* Sync lock = ...;
|
||||
* private static boolean trySwap(Cell a, Cell b) {
|
||||
* a.lock.acquire();
|
||||
* try {
|
||||
* if (!b.lock.attempt(0))
|
||||
* return false;
|
||||
* try {
|
||||
* long t = a.value;
|
||||
* a.value = b.value;
|
||||
* b.value = t;
|
||||
* return true;
|
||||
* }
|
||||
* finally { other.lock.release(); }
|
||||
* }
|
||||
* finally { lock.release(); }
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* void swapValue(Cell other) {
|
||||
* try {
|
||||
* while (!trySwap(this, other) &&
|
||||
* !tryswap(other, this))
|
||||
* Thread.sleep(1);
|
||||
* }
|
||||
* catch (InterruptedException ex) { return; }
|
||||
* }
|
||||
*}
|
||||
*</pre>
|
||||
* <p>
|
||||
* Interruptions are in general handled as early as possible.
|
||||
* Normally, InterruptionExceptions are thrown
|
||||
* in acquire and attempt(msec) if interruption
|
||||
* is detected upon entry to the method, as well as in any
|
||||
* later context surrounding waits.
|
||||
* However, interruption status is ignored in release();
|
||||
* <p>
|
||||
* Timed versions of attempt report failure via return value.
|
||||
* If so desired, you can transform such constructions to use exception
|
||||
* throws via
|
||||
* <pre>
|
||||
* if (!c.attempt(timeval)) throw new TimeoutException(timeval);
|
||||
* </pre>
|
||||
* <p>
|
||||
* The TimoutSync wrapper class can be used to automate such usages.
|
||||
* <p>
|
||||
* All time values are expressed in milliseconds as longs, which have a maximum
|
||||
* value of Long.MAX_VALUE, or almost 300,000 centuries. It is not
|
||||
* known whether JVMs actually deal correctly with such extreme values.
|
||||
* For convenience, some useful time values are defined as static constants.
|
||||
* <p>
|
||||
* All implementations of the three Sync methods guarantee to
|
||||
* somehow employ Java <code>synchronized</code> methods or blocks,
|
||||
* and so entail the memory operations described in JLS
|
||||
* chapter 17 which ensure that variables are loaded and flushed
|
||||
* within before/after constructions.
|
||||
* <p>
|
||||
* Syncs may also be used in spinlock constructions. Although
|
||||
* it is normally best to just use acquire(), various forms
|
||||
* of busy waits can be implemented. For a simple example
|
||||
* (but one that would probably never be preferable to using acquire()):
|
||||
* <pre>
|
||||
* class X {
|
||||
* Sync lock = ...
|
||||
* void spinUntilAcquired() throws InterruptedException {
|
||||
* // Two phase.
|
||||
* // First spin without pausing.
|
||||
* int purespins = 10;
|
||||
* for (int i = 0; i < purespins; ++i) {
|
||||
* if (lock.attempt(0))
|
||||
* return true;
|
||||
* }
|
||||
* // Second phase - use timed waits
|
||||
* long waitTime = 1; // 1 millisecond
|
||||
* for (;;) {
|
||||
* if (lock.attempt(waitTime))
|
||||
* return true;
|
||||
* else
|
||||
* waitTime = waitTime * 3 / 2 + 1; // increase 50%
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In addition pure synchronization control, Syncs
|
||||
* may be useful in any context requiring before/after methods.
|
||||
* For example, you can use an ObservableSync
|
||||
* (perhaps as part of a LayeredSync) in order to obtain callbacks
|
||||
* before and after each method invocation for a given class.
|
||||
* <p>
|
||||
|
||||
* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
|
||||
**/
|
||||
|
||||
|
||||
public interface Sync {
|
||||
|
||||
/**
|
||||
* Wait (possibly forever) until successful passage.
|
||||
* Fail only upon interuption. Interruptions always result in
|
||||
* `clean' failures. On failure, you can be sure that it has not
|
||||
* been acquired, and that no
|
||||
* corresponding release should be performed. Conversely,
|
||||
* a normal return guarantees that the acquire was successful.
|
||||
**/
|
||||
|
||||
void acquire() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Wait at most msecs to pass; report whether passed.
|
||||
* <p>
|
||||
* The method has best-effort semantics:
|
||||
* The msecs bound cannot
|
||||
* be guaranteed to be a precise upper bound on wait time in Java.
|
||||
* Implementations generally can only attempt to return as soon as possible
|
||||
* after the specified bound. Also, timers in Java do not stop during garbage
|
||||
* collection, so timeouts can occur just because a GC intervened.
|
||||
* So, msecs arguments should be used in
|
||||
* a coarse-grained manner. Further,
|
||||
* implementations cannot always guarantee that this method
|
||||
* will return at all without blocking indefinitely when used in
|
||||
* unintended ways. For example, deadlocks may be encountered
|
||||
* when called in an unintended context.
|
||||
* <p>
|
||||
* @param msecs the number of milleseconds to wait.
|
||||
* An argument less than or equal to zero means not to wait at all.
|
||||
* However, this may still require
|
||||
* access to a synchronization lock, which can impose unbounded
|
||||
* delay if there is a lot of contention among threads.
|
||||
* @return true if acquired
|
||||
**/
|
||||
|
||||
boolean attempt(long msecs) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Potentially enable others to pass.
|
||||
* <p>
|
||||
* Because release does not raise exceptions,
|
||||
* it can be used in `finally' clauses without requiring extra
|
||||
* embedded try/catch blocks. But keep in mind that
|
||||
* as with any java method, implementations may
|
||||
* still throw unchecked exceptions such as Error or NullPointerException
|
||||
* when faced with uncontinuable errors. However, these should normally
|
||||
* only be caught by higher-level error handlers.
|
||||
**/
|
||||
|
||||
void release();
|
||||
|
||||
/** One second, in milliseconds; convenient as a time-out value **/
|
||||
long ONE_SECOND = 1000;
|
||||
|
||||
/** One minute, in milliseconds; convenient as a time-out value **/
|
||||
long ONE_MINUTE = 60 * ONE_SECOND;
|
||||
|
||||
/** One hour, in milliseconds; convenient as a time-out value **/
|
||||
long ONE_HOUR = 60 * ONE_MINUTE;
|
||||
|
||||
/** One day, in milliseconds; convenient as a time-out value **/
|
||||
long ONE_DAY = 24 * ONE_HOUR;
|
||||
|
||||
/** One week, in milliseconds; convenient as a time-out value **/
|
||||
long ONE_WEEK = 7 * ONE_DAY;
|
||||
|
||||
/** One year in milliseconds; convenient as a time-out value **/
|
||||
// Not that it matters, but there is some variation across
|
||||
// standard sources about value at msec precision.
|
||||
// The value used is the same as in java.util.GregorianCalendar
|
||||
long ONE_YEAR = (long)(365.2425 * ONE_DAY);
|
||||
|
||||
/** One century in milliseconds; convenient as a time-out value **/
|
||||
long ONE_CENTURY = 100 * ONE_YEAR;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
public class SyncAdapterLock implements JBLock {
|
||||
private final Sync myAdaptee;
|
||||
|
||||
public SyncAdapterLock(final Sync adaptee) {
|
||||
myAdaptee = adaptee;
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
try {
|
||||
myAdaptee.acquire();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
myAdaptee.release();
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
public class SynchronizedBasedReentrantReadWriteLock implements JBReentrantReadWriteLock {
|
||||
private final SyncAdapterLock myReadLock;
|
||||
private final SyncAdapterLock myWriteLock;
|
||||
private final ReentrantWriterPreferenceReadWriteLock myAdaptee;
|
||||
|
||||
public SynchronizedBasedReentrantReadWriteLock() {
|
||||
myAdaptee = new ReentrantWriterPreferenceReadWriteLock();
|
||||
myReadLock = new SyncAdapterLock(myAdaptee.readLock());
|
||||
myWriteLock = new SyncAdapterLock(myAdaptee.writeLock());
|
||||
}
|
||||
|
||||
public JBLock readLock() {
|
||||
return myReadLock;
|
||||
}
|
||||
|
||||
public JBLock writeLock() {
|
||||
return myWriteLock;
|
||||
}
|
||||
|
||||
public boolean isWriteLockedByCurrentThread() {
|
||||
return myAdaptee.isWriteLockAcquired(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.concurrency;
|
||||
|
||||
/**
|
||||
* A ReadWriteLock that prefers waiting writers over
|
||||
* waiting readers when there is contention. This class
|
||||
* is adapted from the versions described in CPJ, improving
|
||||
* on the ones there a bit by segregating reader and writer
|
||||
* wait queues, which is typically more efficient.
|
||||
* <p>
|
||||
* The locks are <em>NOT</em> reentrant. In particular,
|
||||
* even though it may appear to usually work OK,
|
||||
* a thread holding a read lock should not attempt to
|
||||
* re-acquire it. Doing so risks lockouts when there are
|
||||
* also waiting writers.
|
||||
* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
|
||||
**/
|
||||
|
||||
public class WriterPreferenceReadWriteLock implements ReadWriteLock {
|
||||
|
||||
protected long activeReaders_ = 0;
|
||||
protected Thread activeWriter_ = null;
|
||||
protected long waitingReaders_ = 0;
|
||||
protected long waitingWriters_ = 0;
|
||||
|
||||
|
||||
protected final ReaderLock readerLock_ = new ReaderLock();
|
||||
protected final WriterLock writerLock_ = new WriterLock();
|
||||
|
||||
public Sync writeLock() { return writerLock_; }
|
||||
public Sync readLock() { return readerLock_; }
|
||||
|
||||
/*
|
||||
A bunch of small synchronized methods are needed
|
||||
to allow communication from the Lock objects
|
||||
back to this object, that serves as controller
|
||||
*/
|
||||
|
||||
|
||||
protected synchronized void cancelledWaitingReader() { --waitingReaders_; }
|
||||
protected synchronized void cancelledWaitingWriter() { --waitingWriters_; }
|
||||
|
||||
|
||||
/** Override this method to change to reader preference **/
|
||||
protected boolean allowReader() {
|
||||
return activeWriter_ == null && waitingWriters_ == 0;
|
||||
}
|
||||
|
||||
|
||||
protected synchronized boolean startRead() {
|
||||
boolean allowRead = allowReader();
|
||||
if (allowRead) ++activeReaders_;
|
||||
return allowRead;
|
||||
}
|
||||
|
||||
protected synchronized boolean startWrite() {
|
||||
|
||||
// The allowWrite expression cannot be modified without
|
||||
// also changing startWrite, so is hard-wired
|
||||
|
||||
boolean allowWrite = activeWriter_ == null && activeReaders_ == 0;
|
||||
if (allowWrite) activeWriter_ = Thread.currentThread();
|
||||
return allowWrite;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Each of these variants is needed to maintain atomicity
|
||||
of wait counts during wait loops. They could be
|
||||
made faster by manually inlining each other. We hope that
|
||||
compilers do this for us though.
|
||||
*/
|
||||
|
||||
protected synchronized boolean startReadFromNewReader() {
|
||||
boolean pass = startRead();
|
||||
if (!pass) ++waitingReaders_;
|
||||
return pass;
|
||||
}
|
||||
|
||||
protected synchronized boolean startWriteFromNewWriter() {
|
||||
boolean pass = startWrite();
|
||||
if (!pass) ++waitingWriters_;
|
||||
return pass;
|
||||
}
|
||||
|
||||
protected synchronized boolean startReadFromWaitingReader() {
|
||||
boolean pass = startRead();
|
||||
if (pass) --waitingReaders_;
|
||||
return pass;
|
||||
}
|
||||
|
||||
protected synchronized boolean startWriteFromWaitingWriter() {
|
||||
boolean pass = startWrite();
|
||||
if (pass) --waitingWriters_;
|
||||
return pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called upon termination of a read.
|
||||
* Returns the object to signal to wake up a waiter, or null if no such
|
||||
**/
|
||||
protected synchronized Signaller endRead() {
|
||||
if (--activeReaders_ == 0 && waitingWriters_ > 0)
|
||||
return writerLock_;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called upon termination of a write.
|
||||
* Returns the object to signal to wake up a waiter, or null if no such
|
||||
**/
|
||||
protected synchronized Signaller endWrite() {
|
||||
activeWriter_ = null;
|
||||
if (waitingReaders_ > 0 && allowReader())
|
||||
return readerLock_;
|
||||
else if (waitingWriters_ > 0)
|
||||
return writerLock_;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reader and Writer requests are maintained in two different
|
||||
* wait sets, by two different objects. These objects do not
|
||||
* know whether the wait sets need notification since they
|
||||
* don't know preference rules. So, each supports a
|
||||
* method that can be selected by main controlling object
|
||||
* to perform the notifications. This base class simplifies mechanics.
|
||||
**/
|
||||
|
||||
protected abstract static class Signaller { // base for ReaderLock and WriterLock
|
||||
abstract void signalWaiters();
|
||||
}
|
||||
|
||||
protected class ReaderLock extends Signaller implements Sync {
|
||||
|
||||
public void acquire() throws InterruptedException {
|
||||
//TODO: [not sure why this is necessary but very inperformant] if (Thread.interrupted()) throw new InterruptedException();
|
||||
InterruptedException ie = null;
|
||||
synchronized(this) {
|
||||
if (!startReadFromNewReader()) {
|
||||
for (;;) {
|
||||
try {
|
||||
wait();
|
||||
if (startReadFromWaitingReader())
|
||||
return;
|
||||
}
|
||||
catch(InterruptedException ex){
|
||||
cancelledWaitingReader();
|
||||
ie = ex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ie != null) {
|
||||
// fall through outside synch on interrupt.
|
||||
// This notification is not really needed here,
|
||||
// but may be in plausible subclasses
|
||||
writerLock_.signalWaiters();
|
||||
throw ie;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void release() {
|
||||
Signaller s = endRead();
|
||||
if (s != null) s.signalWaiters();
|
||||
}
|
||||
|
||||
|
||||
synchronized void signalWaiters() {
|
||||
notifyAll(); }
|
||||
|
||||
public boolean attempt(long msecs) throws InterruptedException {
|
||||
//TODO: [not sure why this is necessary but very inperformant] if (Thread.interrupted()) throw new InterruptedException();
|
||||
InterruptedException ie = null;
|
||||
synchronized(this) {
|
||||
if (msecs <= 0)
|
||||
return startRead();
|
||||
else if (startReadFromNewReader())
|
||||
return true;
|
||||
else {
|
||||
long waitTime = msecs;
|
||||
long start = System.currentTimeMillis();
|
||||
for (;;) {
|
||||
try {
|
||||
wait(waitTime); }
|
||||
catch(InterruptedException ex){
|
||||
cancelledWaitingReader();
|
||||
ie = ex;
|
||||
break;
|
||||
}
|
||||
if (startReadFromWaitingReader())
|
||||
return true;
|
||||
else {
|
||||
waitTime = msecs - (System.currentTimeMillis() - start);
|
||||
if (waitTime <= 0) {
|
||||
cancelledWaitingReader();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// safeguard on interrupt or timeout:
|
||||
writerLock_.signalWaiters();
|
||||
if (ie != null) throw ie;
|
||||
else return false; // timed out
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected class WriterLock extends Signaller implements Sync {
|
||||
|
||||
public void acquire() throws InterruptedException {
|
||||
if (Thread.interrupted()) throw new InterruptedException();
|
||||
InterruptedException ie = null;
|
||||
synchronized(this) {
|
||||
if (!startWriteFromNewWriter()) {
|
||||
for (;;) {
|
||||
try {
|
||||
wait();
|
||||
if (startWriteFromWaitingWriter())
|
||||
return;
|
||||
}
|
||||
catch(InterruptedException ex){
|
||||
cancelledWaitingWriter();
|
||||
notify();
|
||||
ie = ex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ie != null) {
|
||||
// Fall through outside synch on interrupt.
|
||||
// On exception, we may need to signal readers.
|
||||
// It is not worth checking here whether it is strictly necessary.
|
||||
readerLock_.signalWaiters();
|
||||
throw ie;
|
||||
}
|
||||
}
|
||||
|
||||
public void release(){
|
||||
Signaller s = endWrite();
|
||||
if (s != null) s.signalWaiters();
|
||||
}
|
||||
|
||||
synchronized void signalWaiters() {
|
||||
notify(); }
|
||||
|
||||
public boolean attempt(long msecs) throws InterruptedException {
|
||||
if (Thread.interrupted()) throw new InterruptedException();
|
||||
InterruptedException ie = null;
|
||||
synchronized(this) {
|
||||
if (msecs <= 0)
|
||||
return startWrite();
|
||||
else if (startWriteFromNewWriter())
|
||||
return true;
|
||||
else {
|
||||
long waitTime = msecs;
|
||||
long start = System.currentTimeMillis();
|
||||
for (;;) {
|
||||
try {
|
||||
wait(waitTime); }
|
||||
catch(InterruptedException ex){
|
||||
cancelledWaitingWriter();
|
||||
notify();
|
||||
ie = ex;
|
||||
break;
|
||||
}
|
||||
if (startWriteFromWaitingWriter())
|
||||
return true;
|
||||
else {
|
||||
waitTime = msecs - (System.currentTimeMillis() - start);
|
||||
if (waitTime <= 0) {
|
||||
cancelledWaitingWriter();
|
||||
notify();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readerLock_.signalWaiters();
|
||||
if (ie != null) throw ie;
|
||||
else return false; // timed out
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,21 +20,30 @@
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.util.concurrency.JBLock;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements ConcurrentMap<K, V> {
|
||||
private final JBLock r;
|
||||
private final JBLock w;
|
||||
private final Lock r;
|
||||
private final Lock w;
|
||||
|
||||
private static final StripedLockHolder<ReentrantReadWriteLock> LOCKS = new StripedLockHolder<ReentrantReadWriteLock>(ReentrantReadWriteLock.class) {
|
||||
@NotNull
|
||||
@Override
|
||||
protected ReentrantReadWriteLock create() {
|
||||
return new ReentrantReadWriteLock();
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
final JBReentrantReadWriteLock mutex = StripedJBReentrantReadWriteLocks.getInstance().allocateLock();
|
||||
final ReentrantReadWriteLock mutex = LOCKS.allocateLock();
|
||||
r = mutex.readLock();
|
||||
w = mutex.writeLock();
|
||||
}
|
||||
@@ -49,6 +58,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
super(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -59,6 +69,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -69,6 +80,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -79,6 +91,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -89,6 +102,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -99,6 +113,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
w.lock();
|
||||
try {
|
||||
@@ -109,6 +124,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
w.lock();
|
||||
try {
|
||||
@@ -119,6 +135,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> map) {
|
||||
w.lock();
|
||||
try {
|
||||
@@ -129,6 +146,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
w.lock();
|
||||
try {
|
||||
@@ -139,6 +157,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockPoolSynchronizedMap<K, V> clone() {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -149,6 +168,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -159,6 +179,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -169,6 +190,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
r.lock();
|
||||
try {
|
||||
@@ -179,7 +201,8 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
public boolean replace(K key, V oldValue, V newValue) {
|
||||
@Override
|
||||
public boolean replace(@NotNull K key, @NotNull V oldValue, @NotNull V newValue) {
|
||||
w.lock();
|
||||
try {
|
||||
V prev = get(key);
|
||||
@@ -187,12 +210,7 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newValue == null) {
|
||||
remove(key);
|
||||
}
|
||||
else {
|
||||
put(key, newValue);
|
||||
}
|
||||
put(key, newValue);
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
@@ -200,17 +218,13 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
public V replace(K key, V newValue) {
|
||||
@Override
|
||||
public V replace(@NotNull K key, @NotNull V newValue) {
|
||||
w.lock();
|
||||
try {
|
||||
V prev = get(key);
|
||||
|
||||
if (newValue == null) {
|
||||
remove(key);
|
||||
}
|
||||
else {
|
||||
put(key, newValue);
|
||||
}
|
||||
put(key, newValue);
|
||||
return prev;
|
||||
}
|
||||
finally {
|
||||
@@ -218,7 +232,8 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
public V putIfAbsent(K key, V value) {
|
||||
@Override
|
||||
public V putIfAbsent(@NotNull K key, V value) {
|
||||
w.lock();
|
||||
try {
|
||||
V prev = get(key);
|
||||
@@ -235,7 +250,8 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements Con
|
||||
}
|
||||
}
|
||||
|
||||
public boolean remove(Object key, Object oldValue) {
|
||||
@Override
|
||||
public boolean remove(@NotNull Object key, Object oldValue) {
|
||||
w.lock();
|
||||
try {
|
||||
V currentValue = get(key);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.util.containers;
|
||||
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
public final class StripedJBReentrantReadWriteLocks extends StripedLockHolder<JBReentrantReadWriteLock> {
|
||||
private StripedJBReentrantReadWriteLocks() {
|
||||
super(JBReentrantReadWriteLock.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JBReentrantReadWriteLock create() {
|
||||
return LockFactory.createReadWriteLock();
|
||||
}
|
||||
|
||||
private static final StripedJBReentrantReadWriteLocks INSTANCE = new StripedJBReentrantReadWriteLocks();
|
||||
public static StripedJBReentrantReadWriteLocks getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user