diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ContextInstancesGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ContextInstancesGenerator.java index 01a7ba04fc80a..81e66fc8f5e0f 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ContextInstancesGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ContextInstancesGenerator.java @@ -5,6 +5,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_VOLATILE; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -13,6 +14,7 @@ import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; import java.util.function.Supplier; import org.jboss.jandex.DotName; @@ -88,7 +90,7 @@ Collection generate(DotName scope) { implementRemove(contextInstances, beans, idToField, lockField.getFieldDescriptor()); implementClear(contextInstances, idToField, lockField.getFieldDescriptor()); implementGetAllPresent(contextInstances, idToField, lockField.getFieldDescriptor()); - + implementForEach(contextInstances, idToField, lockField.getFieldDescriptor()); contextInstances.close(); return classOutput.getResources(); @@ -149,6 +151,31 @@ private void implementClear(ClassCreator applicationContextInstances, Map idToField, + FieldDescriptor lockField) { + MethodCreator forEach = contextInstances.getMethodCreator("forEach", void.class, Consumer.class) + .setModifiers(ACC_PUBLIC); + // lock.lock(); + // ContextInstanceHandle copy = this.1; + // lock.unlock(); + // if (copy != null) { + // consumer.accept(copy); + // } + ResultHandle lock = forEach.readInstanceField(lockField, forEach.getThis()); + forEach.invokeInterfaceMethod(MethodDescriptors.LOCK_LOCK, lock); + List results = new ArrayList<>(idToField.size()); + for (FieldDescriptor field : idToField.values()) { + results.add(forEach.readInstanceField(field, forEach.getThis())); + } + forEach.invokeInterfaceMethod(MethodDescriptors.LOCK_UNLOCK, lock); + for (int i = 0; i < results.size(); i++) { + ResultHandle copy = results.get(i); + BytecodeCreator isNotNull = forEach.ifNotNull(copy).trueBranch(); + isNotNull.invokeInterfaceMethod(MethodDescriptors.CONSUMER_ACCEPT, forEach.getMethodParam(0), copy); + } + forEach.returnVoid(); + } + private void implementRemove(ClassCreator contextInstances, List applicationScopedBeans, Map idToField, FieldDescriptor lockField) { MethodCreator remove = contextInstances diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/MethodDescriptors.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/MethodDescriptors.java index 8cc52eb815fb9..79b2f7af860b2 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/MethodDescriptors.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/MethodDescriptors.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -63,6 +64,9 @@ public final class MethodDescriptors { public static final MethodDescriptor SUPPLIER_GET = MethodDescriptor.ofMethod(Supplier.class, "get", Object.class); + public static final MethodDescriptor CONSUMER_ACCEPT = MethodDescriptor.ofMethod(Consumer.class, "accept", + void.class, Object.class); + public static final MethodDescriptor CREATIONAL_CTX_CHILD = MethodDescriptor.ofMethod(CreationalContextImpl.class, "child", CreationalContextImpl.class, CreationalContext.class); diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/AbstractSharedContext.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/AbstractSharedContext.java index 748fae45d3fb7..111f18f174d1b 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/AbstractSharedContext.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/AbstractSharedContext.java @@ -1,9 +1,6 @@ package io.quarkus.arc.impl; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -87,7 +84,11 @@ public void destroy(Contextual contextual) { @Override public synchronized void destroy() { - Set> values = instances.getAllPresent(); + List> values = new LinkedList<>(); + instances.forEach(values::add); + if (values.isEmpty()) { + return; + } // Destroy the producers first for (Iterator> iterator = values.iterator(); iterator.hasNext();) { ContextInstanceHandle instanceHandle = iterator.next(); diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java index fd89543cbc65b..498a4110fba18 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java @@ -1,6 +1,7 @@ package io.quarkus.arc.impl; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Supplier; import io.quarkus.arc.ContextInstanceHandle; @@ -38,4 +39,9 @@ public void clear() { instances.clear(); } + @Override + public void forEach(Consumer> handleConsumer) { + instances.forEachValue(handleConsumer); + } + } diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ContextInstances.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ContextInstances.java index 76ca4ad531e6f..7c0557215ef57 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ContextInstances.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ContextInstances.java @@ -1,6 +1,7 @@ package io.quarkus.arc.impl; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Supplier; import io.quarkus.arc.ContextInstanceHandle; @@ -17,4 +18,6 @@ public interface ContextInstances { void clear(); + void forEach(Consumer> handleConsumer); + } diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/RequestContext.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/RequestContext.java index 08e2043ff9179..40aa2e3240482 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/RequestContext.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/RequestContext.java @@ -210,7 +210,7 @@ public void destroy(ContextState state) { if (reqState.invalidate()) { // Fire an event with qualifier @BeforeDestroyed(RequestScoped.class) if there are any observers for it fireIfNotEmpty(beforeDestroyedNotifier); - reqState.contextInstances.getAllPresent().forEach(this::destroyContextElement); + reqState.contextInstances.forEach(this::destroyContextElement); reqState.contextInstances.clear(); // Fire an event with qualifier @Destroyed(RequestScoped.class) if there are any observers for it fireIfNotEmpty(destroyedNotifier);