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 @Override 069 public void uncaughtException(Thread t, Throwable e) { 070 e.printStackTrace(); 071 } 072 073 } 074 075 private static class CustomThreadFactory implements ThreadFactory { 076 private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); 077 078 private final Thread.UncaughtExceptionHandler handler; 079 080 CustomThreadFactory(Thread.UncaughtExceptionHandler handler) { 081 this.handler = handler; 082 } 083 084 @Override 085 public Thread newThread(Runnable r) { 086 Thread t = defaultFactory.newThread(r); 087 t.setUncaughtExceptionHandler(handler); 088 t.setDaemon(true); //daemonize the thread 089 return t; 090 } 091 }; 092 093 /** 094 * Returns the number of available processors. 095 * 096 * @return number of available processors 097 */ 098 public static int getNumberOfProcessors() { 099 return Runtime.getRuntime().availableProcessors(); 100 } 101 102 /** 103 * Returns the current number of threads. 104 * 105 * @return the current number of threads. 106 */ 107 public static int getNumberOfThreads() { 108 return NTHREADS; 109 } 110 111 /** 112 * Sets the number of threads. If n is not a power-of-two number, then the 113 * number of threads is set to the closest power-of-two number less than n. 114 * 115 * @param n 116 */ 117 public static void setNumberOfThreads(int n) { 118 NTHREADS = prevPow2(n); 119 } 120 121 /** 122 * Returns the minimal size of 1D data for which two threads are used. 123 * 124 * @return the minimal size of 1D data for which two threads are used 125 */ 126 public static int getThreadsBeginN_1D_FFT_2Threads() { 127 return THREADS_BEGIN_N_1D_FFT_2THREADS; 128 } 129 130 /** 131 * Returns the minimal size of 1D data for which four threads are used. 132 * 133 * @return the minimal size of 1D data for which four threads are used 134 */ 135 public static int getThreadsBeginN_1D_FFT_4Threads() { 136 return THREADS_BEGIN_N_1D_FFT_4THREADS; 137 } 138 139 /** 140 * Returns the minimal size of 2D data for which threads are used. 141 * 142 * @return the minimal size of 2D data for which threads are used 143 */ 144 public static int getThreadsBeginN_2D() { 145 return THREADS_BEGIN_N_2D; 146 } 147 148 /** 149 * Returns the minimal size of 3D data for which threads are used. 150 * 151 * @return the minimal size of 3D data for which threads are used 152 */ 153 public static int getThreadsBeginN_3D() { 154 return THREADS_BEGIN_N_3D; 155 } 156 157 /** 158 * Sets the minimal size of 1D data for which two threads are used. 159 * 160 * @param n 161 * the minimal size of 1D data for which two threads are used 162 */ 163 public static void setThreadsBeginN_1D_FFT_2Threads(int n) { 164 if (n < 512) { 165 THREADS_BEGIN_N_1D_FFT_2THREADS = 512; 166 } else { 167 THREADS_BEGIN_N_1D_FFT_2THREADS = n; 168 } 169 } 170 171 /** 172 * Sets the minimal size of 1D data for which four threads are used. 173 * 174 * @param n 175 * the minimal size of 1D data for which four threads are used 176 */ 177 public static void setThreadsBeginN_1D_FFT_4Threads(int n) { 178 if (n < 512) { 179 THREADS_BEGIN_N_1D_FFT_4THREADS = 512; 180 } else { 181 THREADS_BEGIN_N_1D_FFT_4THREADS = n; 182 } 183 } 184 185 /** 186 * Sets the minimal size of 2D data for which threads are used. 187 * 188 * @param n 189 * the minimal size of 2D data for which threads are used 190 */ 191 public static void setThreadsBeginN_2D(int n) { 192 THREADS_BEGIN_N_2D = n; 193 } 194 195 /** 196 * Sets the minimal size of 3D data for which threads are used. 197 * 198 * @param n 199 * the minimal size of 3D data for which threads are used 200 */ 201 public static void setThreadsBeginN_3D(int n) { 202 THREADS_BEGIN_N_3D = n; 203 } 204 205 /** 206 * Resets the minimal size of 1D data for which two and four threads are 207 * used. 208 */ 209 public static void resetThreadsBeginN_FFT() { 210 THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; 211 THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; 212 } 213 214 /** 215 * Resets the minimal size of 2D and 3D data for which threads are used. 216 */ 217 public static void resetThreadsBeginN() { 218 THREADS_BEGIN_N_2D = 65536; 219 THREADS_BEGIN_N_3D = 65536; 220 } 221 222 /** 223 * Returns the closest power-of-two number greater than or equal to x. 224 * 225 * @param x 226 * @return the closest power-of-two number greater than or equal to x 227 */ 228 public static int nextPow2(int x) { 229 if (x < 1) 230 throw new IllegalArgumentException("x must be greater or equal 1"); 231 if ((x & (x - 1)) == 0) { 232 return x; // x is already a power-of-two number 233 } 234 x |= (x >>> 1); 235 x |= (x >>> 2); 236 x |= (x >>> 4); 237 x |= (x >>> 8); 238 x |= (x >>> 16); 239 x |= (x >>> 32); 240 return x + 1; 241 } 242 243 /** 244 * Returns the closest power-of-two number less than or equal to x. 245 * 246 * @param x 247 * @return the closest power-of-two number less then or equal to x 248 */ 249 public static int prevPow2(int x) { 250 if (x < 1) 251 throw new IllegalArgumentException("x must be greater or equal 1"); 252 return (int) Math.pow(2, Math.floor(Math.log(x) / Math.log(2))); 253 } 254 255 /** 256 * Checks if x is a power-of-two number. 257 * 258 * @param x 259 * @return true if x is a power-of-two number 260 */ 261 public static boolean isPowerOf2(int x) { 262 if (x <= 0) 263 return false; 264 else 265 return (x & (x - 1)) == 0; 266 } 267 268 /** 269 * Causes the currently executing thread to sleep (temporarily cease 270 * execution) for the specified number of milliseconds. 271 * 272 * @param millis 273 */ 274 public static void sleep(long millis) { 275 try { 276 Thread.sleep(5000); 277 } catch (InterruptedException e) { 278 e.printStackTrace(); 279 } 280 } 281 282 /** 283 * Submits a Runnable task for execution and returns a Future representing 284 * that task. 285 * 286 * @param task a Runnable task for execution 287 * @return a Future representing the task 288 */ 289 public static Future<?> submit(Runnable task) { 290 return THREAD_POOL.submit(task); 291 } 292 293 /** 294 * Waits for all threads to complete computation. 295 * 296 * @param futures 297 */ 298 public static void waitForCompletion(Future<?>[] futures) { 299 int size = futures.length; 300 try { 301 for (int j = 0; j < size; j++) { 302 futures[j].get(); 303 } 304 } catch (ExecutionException ex) { 305 ex.printStackTrace(); 306 } catch (InterruptedException e) { 307 e.printStackTrace(); 308 } 309 } 310}