001/* ***** BEGIN LICENSE BLOCK *****
002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003 *
004 * The contents of this file are subject to the Mozilla Public License Version
005 * 1.1 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 * http://www.mozilla.org/MPL/
008 *
009 * Software distributed under the License is distributed on an "AS IS" basis,
010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011 * for the specific language governing rights and limitations under the
012 * License.
013 *
014 * The Original Code is Parallel Colt.
015 *
016 * The Initial Developer of the Original Code is
017 * Piotr Wendykier, Emory University.
018 * Portions created by the Initial Developer are Copyright (C) 2007-2009
019 * the Initial Developer. All Rights Reserved.
020 *
021 * Alternatively, the contents of this file may be used under the terms of
022 * either the GNU General Public License Version 2 or later (the "GPL"), or
023 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
024 * in which case the provisions of the GPL or the LGPL are applicable instead
025 * of those above. If you wish to allow use of your version of this file only
026 * under the terms of either the GPL or the LGPL, and not to allow others to
027 * use your version of this file under the terms of the MPL, indicate your
028 * decision by deleting the provisions above and replace them with the notice
029 * and other provisions required by the GPL or the LGPL. If you do not delete
030 * the provisions above, a recipient may use your version of this file under
031 * the terms of any one of the MPL, the GPL or the LGPL.
032 *
033 * ***** END LICENSE BLOCK ***** */
034package edu.emory.mathcs.utils;
035
036import java.util.concurrent.ExecutionException;
037import java.util.concurrent.ExecutorService;
038import java.util.concurrent.Executors;
039import java.util.concurrent.Future;
040import java.util.concurrent.ThreadFactory;
041
042/**
043 * Concurrency utilities.
044 * 
045 * @author Piotr Wendykier (piotr.wendykier@gmail.com)
046 */
047public class ConcurrencyUtils {
048    /**
049     * Thread pool.
050     */
051    private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(new CustomThreadFactory(new CustomExceptionHandler()));
052
053    private static int THREADS_BEGIN_N_1D_FFT_2THREADS = 8192;
054
055    private static int THREADS_BEGIN_N_1D_FFT_4THREADS = 65536;
056
057    private static int THREADS_BEGIN_N_2D = 65536;
058
059    private static int THREADS_BEGIN_N_3D = 65536;
060
061    private static int NTHREADS = prevPow2(getNumberOfProcessors());
062
063    private ConcurrencyUtils() {
064
065    }
066
067    private static class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
068        public void uncaughtException(Thread t, Throwable e) {
069            e.printStackTrace();
070        }
071
072    }
073
074    private static class CustomThreadFactory implements ThreadFactory {
075        private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
076
077        private final Thread.UncaughtExceptionHandler handler;
078
079        CustomThreadFactory(Thread.UncaughtExceptionHandler handler) {
080            this.handler = handler;
081        }
082
083        public Thread newThread(Runnable r) {
084            Thread t = defaultFactory.newThread(r);
085            t.setUncaughtExceptionHandler(handler);
086            t.setDaemon(true); //daemonize the thread
087            return t;
088        }
089    };
090
091    /**
092     * Returns the number of available processors.
093     * 
094     * @return number of available processors
095     */
096    public static int getNumberOfProcessors() {
097        return Runtime.getRuntime().availableProcessors();
098    }
099
100    /**
101     * Returns the current number of threads.
102     * 
103     * @return the current number of threads.
104     */
105    public static int getNumberOfThreads() {
106        return NTHREADS;
107    }
108
109    /**
110     * Sets the number of threads. If n is not a power-of-two number, then the
111     * number of threads is set to the closest power-of-two number less than n.
112     * 
113     * @param n
114     */
115    public static void setNumberOfThreads(int n) {
116        NTHREADS = prevPow2(n);
117    }
118
119    /**
120     * Returns the minimal size of 1D data for which two threads are used.
121     * 
122     * @return the minimal size of 1D data for which two threads are used
123     */
124    public static int getThreadsBeginN_1D_FFT_2Threads() {
125        return THREADS_BEGIN_N_1D_FFT_2THREADS;
126    }
127
128    /**
129     * Returns the minimal size of 1D data for which four threads are used.
130     * 
131     * @return the minimal size of 1D data for which four threads are used
132     */
133    public static int getThreadsBeginN_1D_FFT_4Threads() {
134        return THREADS_BEGIN_N_1D_FFT_4THREADS;
135    }
136
137    /**
138     * Returns the minimal size of 2D data for which threads are used.
139     * 
140     * @return the minimal size of 2D data for which threads are used
141     */
142    public static int getThreadsBeginN_2D() {
143        return THREADS_BEGIN_N_2D;
144    }
145
146    /**
147     * Returns the minimal size of 3D data for which threads are used.
148     * 
149     * @return the minimal size of 3D data for which threads are used
150     */
151    public static int getThreadsBeginN_3D() {
152        return THREADS_BEGIN_N_3D;
153    }
154
155    /**
156     * Sets the minimal size of 1D data for which two threads are used.
157     * 
158     * @param n
159     *            the minimal size of 1D data for which two threads are used
160     */
161    public static void setThreadsBeginN_1D_FFT_2Threads(int n) {
162        if (n < 512) {
163            THREADS_BEGIN_N_1D_FFT_2THREADS = 512;
164        } else {
165            THREADS_BEGIN_N_1D_FFT_2THREADS = n;
166        }
167    }
168
169    /**
170     * Sets the minimal size of 1D data for which four threads are used.
171     * 
172     * @param n
173     *            the minimal size of 1D data for which four threads are used
174     */
175    public static void setThreadsBeginN_1D_FFT_4Threads(int n) {
176        if (n < 512) {
177            THREADS_BEGIN_N_1D_FFT_4THREADS = 512;
178        } else {
179            THREADS_BEGIN_N_1D_FFT_4THREADS = n;
180        }
181    }
182
183    /**
184     * Sets the minimal size of 2D data for which threads are used.
185     * 
186     * @param n
187     *            the minimal size of 2D data for which threads are used
188     */
189    public static void setThreadsBeginN_2D(int n) {
190        THREADS_BEGIN_N_2D = n;
191    }
192
193    /**
194     * Sets the minimal size of 3D data for which threads are used.
195     * 
196     * @param n
197     *            the minimal size of 3D data for which threads are used
198     */
199    public static void setThreadsBeginN_3D(int n) {
200        THREADS_BEGIN_N_3D = n;
201    }
202
203    /**
204     * Resets the minimal size of 1D data for which two and four threads are
205     * used.
206     */
207    public static void resetThreadsBeginN_FFT() {
208        THREADS_BEGIN_N_1D_FFT_2THREADS = 8192;
209        THREADS_BEGIN_N_1D_FFT_4THREADS = 65536;
210    }
211
212    /**
213     * Resets the minimal size of 2D and 3D data for which threads are used.
214     */
215    public static void resetThreadsBeginN() {
216        THREADS_BEGIN_N_2D = 65536;
217        THREADS_BEGIN_N_3D = 65536;
218    }
219
220    /**
221     * Returns the closest power-of-two number greater than or equal to x.
222     * 
223     * @param x
224     * @return the closest power-of-two number greater than or equal to x
225     */
226    public static int nextPow2(int x) {
227        if (x < 1)
228            throw new IllegalArgumentException("x must be greater or equal 1");
229        if ((x & (x - 1)) == 0) {
230            return x; // x is already a power-of-two number 
231        }
232        x |= (x >>> 1);
233        x |= (x >>> 2);
234        x |= (x >>> 4);
235        x |= (x >>> 8);
236        x |= (x >>> 16);
237        x |= (x >>> 32);
238        return x + 1;
239    }
240
241    /**
242     * Returns the closest power-of-two number less than or equal to x.
243     * 
244     * @param x
245     * @return the closest power-of-two number less then or equal to x
246     */
247    public static int prevPow2(int x) {
248        if (x < 1)
249            throw new IllegalArgumentException("x must be greater or equal 1");
250        return (int) Math.pow(2, Math.floor(Math.log(x) / Math.log(2)));
251    }
252
253    /**
254     * Checks if x is a power-of-two number.
255     * 
256     * @param x
257     * @return true if x is a power-of-two number
258     */
259    public static boolean isPowerOf2(int x) {
260        if (x <= 0)
261            return false;
262        else
263            return (x & (x - 1)) == 0;
264    }
265
266    /**
267     * Causes the currently executing thread to sleep (temporarily cease
268     * execution) for the specified number of milliseconds.
269     * 
270     * @param millis
271     */
272    public static void sleep(long millis) {
273        try {
274            Thread.sleep(5000);
275        } catch (InterruptedException e) {
276            e.printStackTrace();
277        }
278    }
279
280    /**
281     * Submits a Runnable task for execution and returns a Future representing
282     * that task.
283     * 
284     * @param task a Runnable task for execution
285     * @return a Future representing the task
286     */
287    public static Future<?> submit(Runnable task) {
288        return THREAD_POOL.submit(task);
289    }
290
291    /**
292     * Waits for all threads to complete computation.
293     * 
294     * @param futures
295     */
296    public static void waitForCompletion(Future<?>[] futures) {
297        int size = futures.length;
298        try {
299            for (int j = 0; j < size; j++) {
300                futures[j].get();
301            }
302        } catch (ExecutionException ex) {
303            ex.printStackTrace();
304        } catch (InterruptedException e) {
305            e.printStackTrace();
306        }
307    }
308}