Skip to content

Commit

Permalink
Avoid re-initializing factories that are already initialized. This is…
Browse files Browse the repository at this point in the history
… necessary because we share the internal factory implementation, which leads to initialize(..) being called multiple times. There are other consequences/quirks of this, but re-initialization is the worst of it.

PiperOrigin-RevId: 530339379
  • Loading branch information
sameb authored and Guice Team committed May 8, 2023
1 parent 9ac4767 commit 40a5bcf
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
23 changes: 23 additions & 0 deletions core/src/com/google/inject/internal/RealMapBinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ private static final class RealProviderMapProvider<K, V>
extends RealMapBinderProviderWithDependencies<K, V, Map<K, Provider<V>>> {
private Map<K, Provider<V>> mapOfProviders;
private Set<Dependency<?>> dependencies = RealMapBinder.MODULE_DEPENDENCIES;
private boolean initialized;

private RealProviderMapProvider(BindingSelection<K, V> bindingSelection) {
super(bindingSelection);
Expand All @@ -713,6 +714,10 @@ public Set<Dependency<?>> getDependencies() {

@Override
protected void doInitialize(InjectorImpl injector, Errors errors) {
if (initialized) {
return;
}
initialized = true;
ImmutableMap.Builder<K, Provider<V>> mapOfProvidersBuilder = ImmutableMap.builder();
ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
for (Map.Entry<K, Binding<V>> entry : bindingSelection.getMapBindings().entrySet()) {
Expand Down Expand Up @@ -743,6 +748,8 @@ private static final class RealMapProvider<K, V>

K[] keys;

private boolean initialized = false;

RealMapProvider(BindingSelection<K, V> bindingSelection) {
super(bindingSelection);
}
Expand All @@ -753,6 +760,10 @@ BindingSelection<K, V> getBindingSelection() {

@Override
protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException {
if (initialized) {
return;
}
initialized = true;
@SuppressWarnings("unchecked")
K[] keysArray = (K[]) new Object[bindingSelection.getMapBindings().size()];
keys = keysArray;
Expand Down Expand Up @@ -1079,6 +1090,7 @@ private static final class RealProviderMultimapProvider<K, V>
extends RealMultimapBinderProviderWithDependencies<K, V, Map<K, Set<Provider<V>>>> {
private Map<K, Set<Provider<V>>> multimapOfProviders;
private Set<Dependency<?>> dependencies = RealMapBinder.MODULE_DEPENDENCIES;
private boolean initialized;

private RealProviderMultimapProvider(Key<Map<K, V>> mapKey) {
super(mapKey);
Expand All @@ -1091,6 +1103,10 @@ public Set<Dependency<?>> getDependencies() {

@Override
protected void doInitialize(InjectorImpl injector, Errors errors) {
if (initialized) {
return;
}
initialized = true;
ImmutableMap.Builder<K, Set<Provider<V>>> multimapOfProvidersBuilder =
ImmutableMap.builder();
ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
Expand Down Expand Up @@ -1141,6 +1157,8 @@ private PerKeyData(K key, Binding<V>[] bindings, SingleParameterInjector<V>[] in

private PerKeyData<K, V>[] perKeyDatas;

private boolean initialized = false;

private RealMultimapProvider(Key<Map<K, V>> mapKey) {
super(mapKey);
}
Expand All @@ -1152,6 +1170,11 @@ public Set<Dependency<?>> getDependencies() {

@Override
protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException {
if (initialized) {
return;
}
initialized = true;

@SuppressWarnings({"unchecked", "rawtypes"})
PerKeyData<K, V>[] typedPerKeyData =
new PerKeyData[bindingSelection.getMapBindings().size()];
Expand Down
12 changes: 10 additions & 2 deletions core/src/com/google/inject/internal/RealOptionalBinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ public int hashCode() {
private abstract static class RealOptionalBinderProviderWithDependencies<T, P>
extends InternalProviderInstanceBindingImpl.Factory<P> {
protected final BindingSelection<T> bindingSelection;
private boolean initialized = false;

RealOptionalBinderProviderWithDependencies(BindingSelection<T> bindingSelection) {
// We need delayed initialization so we can detect jit bindings created by other bindings
Expand All @@ -717,8 +718,15 @@ private abstract static class RealOptionalBinderProviderWithDependencies<T, P>

@Override
final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
bindingSelection.initialize(injector, errors);
doInitialize();
if (!initialized) {
initialized = true;
// Note that bindingSelection.initialize has its own guard, because multiple Factory impls
// will delegate to the same bindingSelection (intentionally). The selection has some
// initialization, and each factory impl has other initialization that it may additionally
// do.
bindingSelection.initialize(injector, errors);
doInitialize();
}
}

/**
Expand Down

0 comments on commit 40a5bcf

Please sign in to comment.