All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.jet.storage.LockBasedLazyResolveStorageManager Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2013 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 org.jetbrains.jet.storage;

import com.google.common.collect.ImmutableMap;
import com.intellij.util.containers.ConcurrentWeakValueHashMap;
import kotlin.Function0;
import kotlin.Function1;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.Diagnostics;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;

import java.util.Collection;
import java.util.concurrent.locks.Lock;

// This class is kept under the same package as LockBasedStorageManager to get access to its protected members
// Otherwise wed have to expose the lock which is worse than have such a hackish class placement
public class LockBasedLazyResolveStorageManager implements LazyResolveStorageManager {

    private final LockBasedStorageManager storageManager;

    public LockBasedLazyResolveStorageManager(@NotNull LockBasedStorageManager storageManager) {
        this.storageManager = storageManager;
    }

    @Override
    @NotNull
    public  MemoizedFunctionToNotNull createWeaklyRetainedMemoizedFunction(
            @NotNull Function1 compute
    ) {
        return storageManager.createMemoizedFunction(compute, new ConcurrentWeakValueHashMap());
    }

    @NotNull
    @Override
    public  MemoizedFunctionToNullable createWeaklyRetainedMemoizedFunctionWithNullableValues(
            @NotNull Function1 compute
    ) {
        return storageManager.createMemoizedFunctionWithNullableValues(compute, new ConcurrentWeakValueHashMap());
    }

    @NotNull
    @Override
    public BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace) {
        // It seems safe to have a separate lock for traces:
        // no other locks will be acquired inside the trace operations
        return new LockProtectedTrace(storageManager.lock, originalTrace);
    }

    @NotNull
    @Override
    public  MemoizedFunctionToNotNull createMemoizedFunction(@NotNull Function1 compute) {
        return storageManager.createMemoizedFunction(compute);
    }

    @NotNull
    @Override
    public  MemoizedFunctionToNullable createMemoizedFunctionWithNullableValues(@NotNull Function1 compute) {
        return storageManager.createMemoizedFunctionWithNullableValues(compute);
    }

    @NotNull
    @Override
    public  NotNullLazyValue createLazyValue(@NotNull Function0 computable) {
        return storageManager.createLazyValue(computable);
    }

    @NotNull
    @Override
    public  NotNullLazyValue createRecursionTolerantLazyValue(
            @NotNull Function0 computable,
            @NotNull T onRecursiveCall
    ) {
        return storageManager.createRecursionTolerantLazyValue(computable, onRecursiveCall);
    }

    @NotNull
    @Override
    public  NotNullLazyValue createLazyValueWithPostCompute(
            @NotNull Function0 computable,
            @Nullable Function1 onRecursiveCall,
            @NotNull Function1 postCompute
    ) {
        return storageManager.createLazyValueWithPostCompute(computable, onRecursiveCall, postCompute);
    }

    @NotNull
    @Override
    public  NullableLazyValue createNullableLazyValue(@NotNull Function0 computable) {
        return storageManager.createNullableLazyValue(computable);
    }

    @NotNull
    @Override
    public  NullableLazyValue createRecursionTolerantNullableLazyValue(
            @NotNull Function0 computable,
            T onRecursiveCall
    ) {
        return storageManager.createRecursionTolerantNullableLazyValue(computable, onRecursiveCall);
    }

    @NotNull
    @Override
    public  NullableLazyValue createNullableLazyValueWithPostCompute(
            @NotNull Function0 computable,
            @NotNull Function1 postCompute
    ) {
        return storageManager.createNullableLazyValueWithPostCompute(computable, postCompute);
    }

    @Override
    public  T compute(@NotNull Function0 computable) {
        return storageManager.compute(computable);
    }

    private static class LockProtectedContext implements BindingContext {
        private final Lock lock;
        private final BindingContext context;

        private LockProtectedContext(Lock lock, BindingContext context) {
            this.lock = lock;
            this.context = context;
        }

        @NotNull
        @Override
        public Diagnostics getDiagnostics() {
            lock.lock();
            try {
                return context.getDiagnostics();
            }
            finally {
                lock.unlock();
            }
        }

        @Nullable
        @Override
        public  V get(ReadOnlySlice slice, K key) {
            lock.lock();
            try {
                return context.get(slice, key);
            }
            finally {
                lock.unlock();
            }
        }

        @NotNull
        @Override
        public  Collection getKeys(WritableSlice slice) {
            lock.lock();
            try {
                return context.getKeys(slice);
            }
            finally {
                lock.unlock();
            }
        }

        @NotNull
        @Override
        @TestOnly
        public  ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) {
            lock.lock();
            try {
                return context.getSliceContents(slice);
            }
            finally {
                lock.unlock();
            }
        }
    }

    private static class LockProtectedTrace implements BindingTrace {
        private final Lock lock;
        private final BindingTrace trace;
        private final BindingContext context;

        public LockProtectedTrace(@NotNull Lock lock, @NotNull BindingTrace trace) {
            this.lock = lock;
            this.trace = trace;
            this.context = new LockProtectedContext(lock, trace.getBindingContext());
        }

        @NotNull
        @Override
        public BindingContext getBindingContext() {
            return context;
        }

        @Override
        public  void record(WritableSlice slice, K key, V value) {
            lock.lock();
            try {
                trace.record(slice, key, value);
            }
            finally {
                lock.unlock();
            }
        }

        @Override
        public  void record(WritableSlice slice, K key) {
            lock.lock();
            try {
                trace.record(slice, key);
            }
            finally {
                lock.unlock();
            }
        }

        @Override
        @Nullable
        public  V get(ReadOnlySlice slice, K key) {
            lock.lock();
            try {
                return trace.get(slice, key);
            }
            finally {
                lock.unlock();
            }
        }

        @Override
        @NotNull
        public  Collection getKeys(WritableSlice slice) {
            lock.lock();
            try {
                return trace.getKeys(slice);
            }
            finally {
                lock.unlock();
            }
        }

        @Override
        public void report(@NotNull Diagnostic diagnostic) {
            lock.lock();
            try {
                trace.report(diagnostic);
            }
            finally {
                lock.unlock();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy