001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.lazy.storage;
018
019 import com.google.common.collect.ImmutableMap;
020 import com.intellij.util.containers.ConcurrentWeakValueHashMap;
021 import jet.Function1;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.annotations.TestOnly;
025 import org.jetbrains.jet.lang.diagnostics.Diagnostic;
026 import org.jetbrains.jet.lang.resolve.BindingContext;
027 import org.jetbrains.jet.lang.resolve.BindingTrace;
028 import org.jetbrains.jet.lang.resolve.Diagnostics;
029 import org.jetbrains.jet.storage.LockBasedStorageManager;
030 import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
031 import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
032 import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
033 import org.jetbrains.jet.util.slicedmap.WritableSlice;
034
035 import java.util.Collection;
036 import java.util.concurrent.locks.Lock;
037
038 public class LockBasedLazyResolveStorageManager extends LockBasedStorageManager implements LazyResolveStorageManager {
039
040 @Override
041 @NotNull
042 public <K, V> MemoizedFunctionToNotNull<K, V> createWeaklyRetainedMemoizedFunction(
043 @NotNull Function1<K, V> compute
044 ) {
045 return super.createMemoizedFunction(compute, new ConcurrentWeakValueHashMap<K, Object>());
046 }
047
048 @NotNull
049 @Override
050 public <K, V> MemoizedFunctionToNullable<K, V> createWeaklyRetainedMemoizedFunctionWithNullableValues(
051 @NotNull Function1<K, V> compute
052 ) {
053 return super.createMemoizedFunctionWithNullableValues(compute, new ConcurrentWeakValueHashMap<K, Object>());
054 }
055
056 @NotNull
057 @Override
058 public BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace) {
059 // It seems safe to have a separate lock for traces:
060 // no other locks will be acquired inside the trace operations
061 return new LockProtectedTrace(lock, originalTrace);
062 }
063
064 private static class LockProtectedContext implements BindingContext {
065 private final Lock lock;
066 private final BindingContext context;
067
068 private LockProtectedContext(Lock lock, BindingContext context) {
069 this.lock = lock;
070 this.context = context;
071 }
072
073 @NotNull
074 @Override
075 public Diagnostics getDiagnostics() {
076 lock.lock();
077 try {
078 return context.getDiagnostics();
079 }
080 finally {
081 lock.unlock();
082 }
083 }
084
085 @Nullable
086 @Override
087 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
088 lock.lock();
089 try {
090 return context.get(slice, key);
091 }
092 finally {
093 lock.unlock();
094 }
095 }
096
097 @NotNull
098 @Override
099 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
100 lock.lock();
101 try {
102 return context.getKeys(slice);
103 }
104 finally {
105 lock.unlock();
106 }
107 }
108
109 @NotNull
110 @Override
111 @TestOnly
112 public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
113 lock.lock();
114 try {
115 return context.getSliceContents(slice);
116 }
117 finally {
118 lock.unlock();
119 }
120 }
121 }
122
123 private static class LockProtectedTrace implements BindingTrace {
124 private final Lock lock;
125 private final BindingTrace trace;
126 private final BindingContext context;
127
128 public LockProtectedTrace(@NotNull Lock lock, @NotNull BindingTrace trace) {
129 this.lock = lock;
130 this.trace = trace;
131 this.context = new LockProtectedContext(lock, trace.getBindingContext());
132 }
133
134 @Override
135 public BindingContext getBindingContext() {
136 return context;
137 }
138
139 @Override
140 public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
141 lock.lock();
142 try {
143 trace.record(slice, key, value);
144 }
145 finally {
146 lock.unlock();
147 }
148 }
149
150 @Override
151 public <K> void record(WritableSlice<K, Boolean> slice, K key) {
152 lock.lock();
153 try {
154 trace.record(slice, key);
155 }
156 finally {
157 lock.unlock();
158 }
159 }
160
161 @Override
162 @Nullable
163 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
164 lock.lock();
165 try {
166 return trace.get(slice, key);
167 }
168 finally {
169 lock.unlock();
170 }
171 }
172
173 @Override
174 @NotNull
175 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
176 lock.lock();
177 try {
178 return trace.getKeys(slice);
179 }
180 finally {
181 lock.unlock();
182 }
183 }
184
185 @Override
186 public void report(@NotNull Diagnostic diagnostic) {
187 lock.lock();
188 try {
189 trace.report(diagnostic);
190 }
191 finally {
192 lock.unlock();
193 }
194 }
195 }
196 }