mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
thread safety
This commit is contained in:
+46
-22
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.reference;
|
||||
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.BitUtil;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -36,18 +36,17 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class RefEntityImpl implements RefEntity {
|
||||
private static final String NO_NAME = InspectionsBundle.message("inspection.reference.noname");
|
||||
private RefEntityImpl myOwner;
|
||||
protected List<RefEntity> myChildren;
|
||||
abstract class RefEntityImpl implements RefEntity {
|
||||
private RefEntityImpl myOwner; // guarded by myManager.myLock
|
||||
protected List<RefEntity> myChildren; // guarded by myManager.myLock
|
||||
private final String myName;
|
||||
private Map<Key, Object> myUserMap;
|
||||
protected long myFlags;
|
||||
protected final RefManagerImpl myManager;
|
||||
|
||||
protected RefEntityImpl(String name, @NotNull RefManager manager) {
|
||||
RefEntityImpl(@NotNull String name, @NotNull RefManager manager) {
|
||||
myManager = (RefManagerImpl)manager;
|
||||
myName = name != null ? name : NO_NAME;
|
||||
myName = name;
|
||||
myOwner = null;
|
||||
myChildren = null;
|
||||
}
|
||||
@@ -66,32 +65,57 @@ public abstract class RefEntityImpl implements RefEntity {
|
||||
|
||||
@Override
|
||||
public List<RefEntity> getChildren() {
|
||||
return myChildren;
|
||||
return myManager.doRead(new Computable<List<RefEntity>>() {
|
||||
@Override
|
||||
public List<RefEntity> compute() {
|
||||
return myChildren;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefEntity getOwner() {
|
||||
return myOwner;
|
||||
return myManager.doRead(new Computable<RefEntity>() {
|
||||
@Override
|
||||
public RefEntity compute() {
|
||||
return myOwner;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void setOwner(RefEntityImpl owner) {
|
||||
myOwner = owner;
|
||||
protected void setOwner(final RefEntityImpl owner) {
|
||||
myManager.doWrite(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myOwner = owner;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void add(RefEntity child) {
|
||||
if (myChildren == null) {
|
||||
myChildren = new ArrayList<RefEntity>(1);
|
||||
}
|
||||
public void add(@NotNull final RefEntity child) {
|
||||
myManager.doWrite(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myChildren == null) {
|
||||
myChildren = new ArrayList<RefEntity>(1);
|
||||
}
|
||||
|
||||
myChildren.add(child);
|
||||
((RefEntityImpl)child).setOwner(this);
|
||||
myChildren.add(child);
|
||||
((RefEntityImpl)child).setOwner(RefEntityImpl.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void removeChild(RefEntity child) {
|
||||
if (myChildren != null) {
|
||||
myChildren.remove(child);
|
||||
((RefEntityImpl)child).setOwner(null);
|
||||
}
|
||||
protected void removeChild(@NotNull final RefEntity child) {
|
||||
myManager.doWrite(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myChildren != null) {
|
||||
myChildren.remove(child);
|
||||
((RefEntityImpl)child).setOwner(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
+23
-2
@@ -59,6 +59,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class RefManagerImpl extends RefManager {
|
||||
@@ -85,7 +86,7 @@ public class RefManagerImpl extends RefManager {
|
||||
private final Map<Key, RefManagerExtension> myExtensions = new HashMap<Key, RefManagerExtension>();
|
||||
private final Map<Language, RefManagerExtension> myLanguageExtensions = new HashMap<Language, RefManagerExtension>();
|
||||
|
||||
private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();
|
||||
private final ReadWriteLock myLock = new ReentrantReadWriteLock();
|
||||
|
||||
public RefManagerImpl(@NotNull Project project, @Nullable AnalysisScope scope, @NotNull GlobalInspectionContext context) {
|
||||
myProject = project;
|
||||
@@ -533,9 +534,9 @@ public class RefManagerImpl extends RefManager {
|
||||
protected <T extends RefElement> T getFromRefTableOrCache(final PsiElement element,
|
||||
@NotNull NullableFactory<T> factory,
|
||||
@Nullable Consumer<T> whenCached) {
|
||||
T result;
|
||||
|
||||
myLock.readLock().lock();
|
||||
T result;
|
||||
try {
|
||||
//noinspection unchecked
|
||||
result = (T)myRefTable.get(ApplicationManager.getApplication().runReadAction(
|
||||
@@ -624,6 +625,26 @@ public class RefManagerImpl extends RefManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void doWrite(@NotNull Runnable runnable) {
|
||||
myLock.writeLock().lock();
|
||||
try {
|
||||
runnable.run();
|
||||
}
|
||||
finally {
|
||||
myLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T doRead(@NotNull Computable<T> runnable) {
|
||||
myLock.readLock().lock();
|
||||
try {
|
||||
return runnable.compute();
|
||||
}
|
||||
finally {
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean belongsToScope(final PsiElement psiElement) {
|
||||
return belongsToScope(psiElement, false);
|
||||
|
||||
+40
-15
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.codeInspection.reference;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -14,32 +29,42 @@ import java.util.ArrayList;
|
||||
* User: anna
|
||||
* Date: 09-Jan-2006
|
||||
*/
|
||||
public class RefModuleImpl extends RefEntityImpl implements RefModule {
|
||||
class RefModuleImpl extends RefEntityImpl implements RefModule {
|
||||
private final Module myModule;
|
||||
|
||||
protected RefModuleImpl(@NotNull Module module, @NotNull RefManager manager) {
|
||||
RefModuleImpl(@NotNull Module module, @NotNull RefManager manager) {
|
||||
super(module.getName(), manager);
|
||||
myModule = module;
|
||||
((RefProjectImpl)manager.getRefProject()).add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(RefEntity child) {
|
||||
if (myChildren == null) {
|
||||
myChildren = new ArrayList<RefEntity>();
|
||||
}
|
||||
myChildren.add(child);
|
||||
public void add(@NotNull final RefEntity child) {
|
||||
myManager.doWrite(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myChildren == null) {
|
||||
myChildren = new ArrayList<RefEntity>();
|
||||
}
|
||||
myChildren.add(child);
|
||||
|
||||
if (child.getOwner() == null) {
|
||||
((RefEntityImpl)child).setOwner(this);
|
||||
}
|
||||
if (child.getOwner() == null) {
|
||||
((RefEntityImpl)child).setOwner(RefModuleImpl.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeChild(RefEntity child) {
|
||||
if (myChildren != null) {
|
||||
myChildren.remove(child);
|
||||
}
|
||||
protected void removeChild(@NotNull final RefEntity child) {
|
||||
myManager.doWrite(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myChildren != null) {
|
||||
myChildren.remove(child);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,7 +94,7 @@ public class RefModuleImpl extends RefEntityImpl implements RefModule {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static RefEntity moduleFromName(final RefManager manager, final String name) {
|
||||
static RefEntity moduleFromName(final RefManager manager, final String name) {
|
||||
return manager.getRefModule(ModuleManager.getInstance(manager.getProject()).findModuleByName(name));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user