2020-11-12 02:13:54 +01:00
|
|
|
package speiger.src.collections.utils;
|
|
|
|
|
2020-12-21 03:05:41 +01:00
|
|
|
import java.util.Random;
|
2020-11-30 02:27:58 +01:00
|
|
|
import java.util.concurrent.ForkJoinPool;
|
|
|
|
import java.util.concurrent.ForkJoinTask;
|
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Helper class that provides functions that are shared within the library.
|
|
|
|
* On top of that it provides some helper functions that allow control of some internals of the Library
|
|
|
|
*/
|
2020-11-12 02:13:54 +01:00
|
|
|
public class SanityChecks
|
|
|
|
{
|
2020-11-26 22:56:15 +01:00
|
|
|
public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
2020-11-30 02:27:58 +01:00
|
|
|
private static ForkJoinPool WORK_POOL = ForkJoinPool.commonPool();
|
2021-01-11 17:53:30 +01:00
|
|
|
private static boolean FORCE_IGNORE_PARALLELISM = false;
|
2020-12-21 03:05:41 +01:00
|
|
|
private static ThreadLocal<Random> RANDOM = ThreadLocal.withInitial(Random::new);
|
2021-01-09 21:41:28 +01:00
|
|
|
private static ThreadLocal<Boolean> FORCE_ASYNC = ThreadLocal.withInitial(() -> false);
|
|
|
|
private static ThreadLocal<Boolean> FORCE_TASK_POOL = ThreadLocal.withInitial(() -> false);
|
2020-11-26 22:56:15 +01:00
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Internal function to cast a Integer to a Byte
|
|
|
|
* @param value that should be turned into a byte
|
|
|
|
* @return the value as a byte
|
|
|
|
* @throws IllegalStateException if the value does not fit within a byte
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static byte castToByte(int value) {
|
2020-11-12 02:13:54 +01:00
|
|
|
if(value > Byte.MAX_VALUE || value < Byte.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Byte[-128,127] range");
|
|
|
|
return (byte)value;
|
|
|
|
}
|
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Internal function to cast a Integer to a Short
|
|
|
|
* @param value that should be turned into a short
|
|
|
|
* @return the value as a short
|
|
|
|
* @throws IllegalStateException if the value does not fit within a short
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static short castToShort(int value) {
|
2020-11-12 02:13:54 +01:00
|
|
|
if(value > Short.MAX_VALUE || value < Short.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Short[-32768,32767] range");
|
|
|
|
return (short)value;
|
|
|
|
}
|
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Internal function to cast a Integer to a Character
|
|
|
|
* @param value that should be turned into a char
|
|
|
|
* @return the value as a char
|
|
|
|
* @throws IllegalStateException if the value does not fit within a char
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static char castToChar(int value) {
|
2020-11-12 02:13:54 +01:00
|
|
|
if(value > Character.MAX_VALUE || value < Character.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Character[0,65535] range");
|
|
|
|
return (char)value;
|
|
|
|
}
|
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Internal function to cast a Double to a Double
|
|
|
|
* @param value that should be turned into a float
|
|
|
|
* @return the value as a float
|
|
|
|
* @throws IllegalStateException if the value does not fit within a float
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static float castToFloat(double value) {
|
2020-11-12 02:13:54 +01:00
|
|
|
if(Double.isNaN(value)) return Float.NaN;
|
|
|
|
if(Double.isInfinite(value)) return value > 0 ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
|
|
|
|
if(value < -Float.MAX_VALUE || value > Float.MAX_VALUE) throw new IllegalStateException("Value ["+value+"] out of Float range");
|
|
|
|
return (float)value;
|
|
|
|
}
|
2020-11-26 22:56:15 +01:00
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Internal function that checks if the given array-size is big enough for the access.
|
|
|
|
* @param arraySize the size of the Array
|
|
|
|
* @param offset the offset of the access
|
|
|
|
* @param accessSize the lenght of the access
|
|
|
|
* @throws IllegalStateException if offset or accessSize is negative or the range goes out of the array-size
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static void checkArrayCapacity(int arraySize, int offset, int accessSize) {
|
2020-11-26 22:56:15 +01:00
|
|
|
if(offset < 0) throw new IllegalStateException("Offset is negative ("+offset+")");
|
|
|
|
else if(accessSize < 0) throw new IllegalStateException("Size is negative ("+accessSize+")");
|
2020-12-21 03:05:41 +01:00
|
|
|
else if(arraySize < offset + accessSize) throw new IndexOutOfBoundsException("Index (" + (offset + accessSize) + ") is not in size (" + arraySize + ")");
|
2020-11-26 22:56:15 +01:00
|
|
|
}
|
2020-11-30 02:27:58 +01:00
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Returns if the current thread-pool can handle multi-threading tasks
|
|
|
|
* @return true if the threadcount is bigger the 1
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static boolean canParallelTask() {
|
2021-04-22 23:02:04 +02:00
|
|
|
return getPool().getParallelism() > 1 || FORCE_IGNORE_PARALLELISM;
|
2020-11-30 02:27:58 +01:00
|
|
|
}
|
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Helper method to start a ForkJoinTask. This method will await the finalization of said task
|
|
|
|
* @param task the Task to invoke
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static <T> void invokeTask(ForkJoinTask<T> task) {
|
2021-01-09 21:41:28 +01:00
|
|
|
if(FORCE_ASYNC.get().booleanValue()) invokeAsyncTask(task);
|
|
|
|
else getPool().invoke(task);
|
2020-11-30 02:27:58 +01:00
|
|
|
}
|
|
|
|
|
2020-12-06 09:32:22 +01:00
|
|
|
/**
|
|
|
|
* Helper method to start a ForkJoinTask. This method will not await the finalization of said task
|
|
|
|
* @param task the Task to invoke
|
|
|
|
*/
|
|
|
|
public static <T> void invokeAsyncTask(ForkJoinTask<T> task) {
|
2021-01-09 21:41:28 +01:00
|
|
|
getPool().execute(task);
|
2020-12-06 09:32:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to control what ForkJoinPool is being used for any given task.
|
|
|
|
* @Note this method is not thread-save. It is only there to provide control over how Library specific Threaded tasks are handled.
|
|
|
|
* @param pool The ForkJoinPool that should receive the tasks. If null {@link ForkJoinPool#commonPool()} is set instead
|
|
|
|
*/
|
2020-11-30 02:27:58 +01:00
|
|
|
public static void setWorkPool(ForkJoinPool pool) {
|
|
|
|
WORK_POOL = pool == null ? ForkJoinPool.commonPool() : pool;
|
|
|
|
}
|
2020-12-21 03:05:41 +01:00
|
|
|
|
2021-01-09 21:41:28 +01:00
|
|
|
private static ForkJoinPool getPool() {
|
|
|
|
if(FORCE_TASK_POOL.get().booleanValue()) {
|
|
|
|
ForkJoinPool pool = ForkJoinTask.getPool();
|
|
|
|
if(pool != null) return pool;
|
|
|
|
}
|
|
|
|
return WORK_POOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to detect if the Current Thread forces not to await task completion.
|
|
|
|
* @return if the Current Thread has not to await task completion.
|
|
|
|
*/
|
|
|
|
public static boolean isForcedAsync() {
|
|
|
|
return FORCE_ASYNC.get().booleanValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to detect if the current thread forces to execute tasks in the current Thread-pool if it is a ForkJoinPool.
|
|
|
|
* @return if the task checks the current pool to be executed in if it is valid.
|
|
|
|
*/
|
|
|
|
public static boolean isForcedTaskPool() {
|
|
|
|
return FORCE_TASK_POOL.get().booleanValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to decide if the current thread should forcefully not wait on tasks to be completed.
|
|
|
|
* @param value it tasks should not be awaited for
|
|
|
|
*/
|
|
|
|
public static void setForcedAsync(boolean value) {
|
|
|
|
FORCE_ASYNC.set(Boolean.valueOf(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to decide if it should be checked for if the current thread is a ThreadPool Worker (ForkJoinPool Worker to be specific) and if tasks should be delegated into it.
|
|
|
|
* @param value if the current thread should check if it is a ThreadPoolWorker.
|
|
|
|
*/
|
|
|
|
public static void setForcedTaskPool(boolean value) {
|
|
|
|
FORCE_TASK_POOL.set(Boolean.valueOf(value));
|
|
|
|
}
|
|
|
|
|
2021-01-11 17:53:30 +01:00
|
|
|
/**
|
|
|
|
* Helper method to decide if Parallelism should be checked or not.
|
|
|
|
* @param value if the Parallelism should be ignored
|
|
|
|
*/
|
|
|
|
public static void setForceIgnoreParallelism(boolean value) {
|
|
|
|
FORCE_IGNORE_PARALLELISM = value;
|
|
|
|
}
|
|
|
|
|
2021-01-09 21:41:28 +01:00
|
|
|
/**
|
|
|
|
* @return Thread Specific Random needed for internal functions in this library.
|
|
|
|
*/
|
2020-12-21 03:05:41 +01:00
|
|
|
public static Random getRandom() {
|
|
|
|
return RANDOM.get();
|
|
|
|
}
|
2020-11-12 02:13:54 +01:00
|
|
|
}
|