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) {
        final ForkJoinPool commonPool = ForkJoinPool.commonPool();

        final int activeThreadCount = commonPool.getActiveThreadCount();

        //The following approach is rather heavy, but there's good chances that there are actually no active threads,
        //so skip it in this case.
        //Additionally, if we can skip this this will prevent us from actually forcing to start all threads in the pool.
        if (activeThreadCount > 0) {
            //TODO we could theoretically improve this by using the system property java.util.concurrent.ForkJoinPool.common.threadFactory
            //and force the common pool to register created threads so that we can reach and reset them.
            CountDownLatch allDone = new CountDownLatch(ForkJoinPool.getCommonPoolParallelism());
            CountDownLatch taskRelease = new CountDownLatch(1);
            for (int i = 0; i < ForkJoinPool.getCommonPoolParallelism(); ++i) {
                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();
            }
        }
    }
}

@@ -724,709 +724,8 @@
 ) %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    
     
@@ -814,20 +814,16 @@
 ism());%0A
-    
         
@@ -882,20 +882,16 @@
         
-    
 for (int
@@ -962,20 +962,29 @@
         
-    
+ForkJoinPool.
 commonPo
@@ -985,16 +985,18 @@
 mmonPool
+()
 .execute
@@ -1029,20 +1029,16 @@
         
-    
 @Overrid
@@ -1039,20 +1039,16 @@
 verride%0A
-    
         
@@ -1095,20 +1095,16 @@
         
-    
 Thread.c
@@ -1174,20 +1174,16 @@
         
-    
 allDone.
@@ -1207,36 +1207,32 @@
                 
-    
 try %7B%0A          
@@ -1237,36 +1237,32 @@
                 
- 
-   
 taskRelease.awai
@@ -1262,28 +1262,24 @@
 se.await();%0A
-    
             
@@ -1337,36 +1337,32 @@
                 
-    
 log.error(%22Faile
@@ -1414,34 +1414,26 @@
             
-  
-  %7D%0A    
+%7D%0A
             
@@ -1450,20 +1450,16 @@
         
-    
 %7D);%0A    
@@ -1458,34 +1458,26 @@
 %7D);%0A        
-   
- 
 %7D%0A
-    
         try 
@@ -1470,36 +1470,32 @@
 %7D%0A        try %7B%0A
-    
             if (
@@ -1541,36 +1541,32 @@
                 
-    
 log.error(%0A     
@@ -1560,20 +1560,16 @@
 .error(%0A
-    
         
@@ -1740,34 +1740,26 @@
             
-    %7D%0A    
+%7D%0A
         %7D ca
@@ -1793,36 +1793,32 @@
 ) %7B%0A            
- 
-   
 log.error(%22Faile
@@ -1862,20 +1862,16 @@
         
-    
 %7D finall
@@ -1870,28 +1870,24 @@
 %7D finally %7B%0A
-    
             
@@ -1911,30 +1911,16 @@
 Down();%0A
-            %7D%0A
         

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