blob: 2470e414bbda18203e68702c7c090bccc225a9b7 [file] [log] [blame]
// Copyright 2014 The Bazel Authors. 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.actions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.MapMaker;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* A registry that keeps a map of artifacts to unique integer ids.
*/
class ArtifactIdRegistry implements ArtifactSerializer, ArtifactDeserializer {
/**
* A sequence of registered artifacts. The position in the list is the artifact's id.
*
* <p>Synchronized using {@link #artifactIdsLock}.
*/
private final List<Artifact> serializedArtifactList = new ArrayList<>();
/**
* A map of artifacts to unique integer ids.
*
* <p>Writes to this map must be synchronized using {@link #artifactIdsLock}, in order to
* maintain consistency with {@link #serializedArtifactList}.
*/
private final ConcurrentMap<Artifact, Integer> serializedArtifactIds =
new MapMaker().concurrencyLevel(1).makeMap();
/**
* A lock for keeping {@code serializedArtifactList} and {@code serializedArtifactIds} in sync.
*/
private ReadWriteLock artifactIdsLock = new ReentrantReadWriteLock();
ArtifactIdRegistry() {
}
@Override
public int getArtifactId(Artifact artifact) {
Integer artifactId = serializedArtifactIds.get(artifact);
if (artifactId == null) {
artifactId = assignArtifactId(artifact);
}
return artifactId;
}
private Integer assignArtifactId(Artifact artifact) {
artifactIdsLock.writeLock().lock();
try {
Integer artifactId = serializedArtifactIds.get(artifact);
if (artifactId == null) {
artifactId = serializedArtifactList.size();
serializedArtifactList.add(artifact);
serializedArtifactIds.put(artifact, artifactId);
}
return artifactId;
} finally {
artifactIdsLock.writeLock().unlock();
}
}
@Override
public Artifact lookupArtifactById(int artifactId) {
artifactIdsLock.readLock().lock();
try {
return serializedArtifactList.get(artifactId);
} finally {
artifactIdsLock.readLock().unlock();
}
}
@Override
public ImmutableList<Artifact> lookupArtifactsByIds(Iterable<Integer> artifactIds) {
int size = Iterables.size(artifactIds);
Artifact[] result = new Artifact[size];
int i = 0;
artifactIdsLock.readLock().lock();
try {
for (int artifactId : artifactIds) {
result[i] = serializedArtifactList.get(artifactId);
i++;
}
} finally {
artifactIdsLock.readLock().unlock();
}
return ImmutableList.copyOf(result);
}
}