/*
 * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.nio.ch;

import java.util.concurrent.*;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
import sun.security.action.GetIntegerAction;

/**
 * Encapsulates a thread pool associated with a channel group.
 */

public class ThreadPool {
    private static final String DEFAULT_THREAD_POOL_THREAD_FACTORY =
        "java.nio.channels.DefaultThreadPool.threadFactory";
    private static final String DEFAULT_THREAD_POOL_INITIAL_SIZE =
        "java.nio.channels.DefaultThreadPool.initialSize";
    private static final ThreadFactory defaultThreadFactory = new ThreadFactory() {
         @Override
         public Thread newThread(Runnable r) {
             Thread t = new Thread(r);
             t.setDaemon(true);
             return t;
        }
     };

    private final ExecutorService executor;

    // indicates if thread pool is fixed size
    private final boolean isFixed;

    // indicates the pool size (for a fixed thread pool configuratin this is
    // the maximum pool size; for other thread pools it is the initial size)
    private final int poolSize;

    private ThreadPool(ExecutorService executor,
                       boolean isFixed,
                       int poolSize)
    {
        this.executor = executor;
        this.isFixed = isFixed;
        this.poolSize = poolSize;
    }

    ExecutorService executor() {
        return executor;
    }

    boolean isFixedThreadPool() {
        return isFixed;
    }

    int poolSize() {
        return poolSize;
    }

    static ThreadFactory defaultThreadFactory() {
        return defaultThreadFactory;
    }

    private static class DefaultThreadPoolHolder {
        final static ThreadPool defaultThreadPool = createDefault();
    }

    // return the default (system-wide) thread pool
    static ThreadPool getDefault() {
        return DefaultThreadPoolHolder.defaultThreadPool;
    }

    // create thread using default settings (configured by system properties)
    static ThreadPool createDefault() {
        // default the number of fixed threads to the hardware core count
        int initialSize = getDefaultThreadPoolInitialSize();
        if (initialSize < 0)
            initialSize = Runtime.getRuntime().availableProcessors();
        // default to thread factory that creates daemon threads
        ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory();
        if (threadFactory == null)
            threadFactory = defaultThreadFactory;
        // create thread pool
        ExecutorService executor =
            new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                   Long.MAX_VALUE, TimeUnit.MILLISECONDS,
                                   new SynchronousQueue<Runnable>(),
                                   threadFactory);
        return new ThreadPool(executor, false, initialSize);
    }

    // create using given parameters
    static ThreadPool create(int nThreads, ThreadFactory factory) {
        if (nThreads <= 0)
            throw new IllegalArgumentException("'nThreads' must be > 0");
        ExecutorService executor = Executors.newFixedThreadPool(nThreads, factory);
        return new ThreadPool(executor, true, nThreads);
    }

    // wrap a user-supplied executor
    public static ThreadPool wrap(ExecutorService executor, int initialSize) {
        if (executor == null)
            throw new NullPointerException("'executor' is null");
        // attempt to check if cached thread pool
        if (executor instanceof ThreadPoolExecutor) {
            int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize();
            if (max == Integer.MAX_VALUE) {
                if (initialSize < 0) {
                    initialSize = Runtime.getRuntime().availableProcessors();
                } else {
                   // not a cached thread pool so ignore initial size
                    initialSize = 0;
                }
            }
        } else {
            // some other type of thread pool
            if (initialSize < 0)
                initialSize = 0;
        }
        return new ThreadPool(executor, false, initialSize);
    }

    private static int getDefaultThreadPoolInitialSize() {
        String propValue = AccessController.doPrivileged(new
            GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE));
        if (propValue != null) {
            try {
                return Integer.parseInt(propValue);
            } catch (NumberFormatException x) {
                throw new Error("Value of property '" + DEFAULT_THREAD_POOL_INITIAL_SIZE +
                    "' is invalid: " + x);
            }
        }
        return -1;
    }

    private static ThreadFactory getDefaultThreadPoolThreadFactory() {
        String propValue = AccessController.doPrivileged(new
            GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY));
        if (propValue != null) {
            try {
                Class<?> c = Class
                    .forName(propValue, true, ClassLoader.getSystemClassLoader());
                return ((ThreadFactory)c.newInstance());
            } catch (ClassNotFoundException x) {
                throw new Error(x);
            } catch (InstantiationException x) {
                throw new Error(x);
            } catch (IllegalAccessException x) {
                throw new Error(x);
            }
        }
        return null;
    }
}
