package io.quarkus.runner.bootstrap;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

import org.jboss.logging.Logger;

public class ForkJoinClassLoading {

    private static final Logger log = Logger.getLogger(ForkJoinClassLoading.class.getName());

    /**
     * A yucky hack, basically attempt to make sure every thread in the common pool has
     * the correct CL.
     * 
     * It's not perfect, but as this only affects test and dev mode and not production it is better
     * than nothing.
     * 
     * Really we should just not use the common pool at all.
     */
    public static void setForkJoinClassLoader(ClassLoader classLoader) {
        CountDownLatch allDone = new CountDownLatch(ForkJoinPool.getCommonPoolParallelism());
        CountDownLatch taskRelease = new CountDownLatch(1);
        for (int i = 0; i < ForkJoinPool.getCommonPoolParallelism(); ++i) {
            ForkJoinPool.commonPool().execute(new Runnable() {
                @Override
                public void run() {
                    Thread.currentThread().setContextClassLoader(classLoader);
                    allDone.countDown();
                    try {
                        taskRelease.await();
                    } catch (InterruptedException e) {
                        log.error("Failed to set fork join ClassLoader", e);
                    }
                }
            });
        }
        try {
            if (!allDone.await(1, TimeUnit.SECONDS)) {
                log.error(
                        "Timed out trying to set fork join ClassLoader, this should never happen unless something has tied up a fork join thread before the app launched");
            }
        } catch (InterruptedException e) {
            log.error("Failed to set fork join ClassLoader", e);
        } finally {
            taskRelease.countDown();
        }
    }
}

@@ -716,24 +716,725 @@
 ssLoader) %7B%0A
+        final ForkJoinPool commonPool = ForkJoinPool.commonPool();%0A%0A        final int activeThreadCount = commonPool.getActiveThreadCount();%0A%0A        //The following approach is rather heavy, but there's good chances that there are actually no active threads,%0A        //so skip it in this case.%0A        //Additionally, if we can skip this this will prevent us from actually forcing to start all threads in the pool.%0A        if (activeThreadCount %3E 0) %7B%0A            //TODO we could theoretically improve this by using the system property java.util.concurrent.ForkJoinPool.common.threadFactory%0A            //and force the common pool to register created threads so that we can reach and reset them.%0A    
         Coun
@@ -1515,16 +1515,20 @@
 ism());%0A
+    
         
@@ -1587,16 +1587,20 @@
         
+    
 for (int
@@ -1671,29 +1671,20 @@
         
-ForkJoinPool.
+    
 commonPo
@@ -1685,18 +1685,16 @@
 mmonPool
-()
 .execute
@@ -1727,16 +1727,20 @@
         
+    
 @Overrid
@@ -1741,16 +1741,20 @@
 verride%0A
+    
         
@@ -1801,16 +1801,20 @@
         
+    
 Thread.c
@@ -1884,16 +1884,20 @@
         
+    
 allDone.
@@ -1921,32 +1921,36 @@
                 
+    
 try %7B%0A          
@@ -1955,32 +1955,36 @@
                 
+ 
+   
 taskRelease.awai
@@ -1984,24 +1984,28 @@
 se.await();%0A
+    
             
@@ -2063,32 +2063,36 @@
                 
+    
 log.error(%22Faile
@@ -2140,34 +2140,42 @@
                 
+  
-%7D%0A
+  %7D%0A    
                 
@@ -2188,16 +2188,20 @@
         
+    
 %7D);%0A    
@@ -2196,34 +2196,42 @@
     %7D);%0A        
+   
+ 
 %7D%0A
+    
         try %7B%0A  
@@ -2220,32 +2220,36 @@
           try %7B%0A
+    
             if (
@@ -2295,32 +2295,36 @@
                 
+    
 log.error(%0A     
@@ -2318,16 +2318,20 @@
 .error(%0A
+    
         
@@ -2498,34 +2498,42 @@
 %22);%0A            
-%7D%0A
+    %7D%0A    
         %7D catch 
@@ -2563,32 +2563,36 @@
 ) %7B%0A            
+ 
+   
 log.error(%22Faile
@@ -2636,16 +2636,20 @@
         
+    
 %7D finall
@@ -2648,24 +2648,28 @@
 %7D finally %7B%0A
+    
             
@@ -2685,32 +2685,46 @@
 se.countDown();%0A
+            %7D%0A
         %7D%0A    %7D%0A

Optimise the strategy we use to reset the classloader in the Common ForkJoin ThreadPool