All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codefilarete.tool.ThreadLocals Maven / Gradle / Ivy

package org.codefilarete.tool;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.codefilarete.tool.function.Hanger;
import org.codefilarete.tool.function.ThrowingConsumer;
import org.codefilarete.tool.function.ThrowingFunction;
import org.codefilarete.tool.function.ThrowingRunnable;
import org.codefilarete.tool.function.ThrowingSupplier;

/**
 * @author Guillaume Mary
 */
public class ThreadLocals {
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 * 
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  void doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, Runnable runnable) {
		doWithThreadLocal(threadLocal, factory, (ThrowingRunnable) runnable::run);
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 *
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  void doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, ThrowingRunnable runnable) 
			throws E {
		doWithThreadLocal(threadLocal, factory, (ThrowingFunction) t -> { runnable.run(); return null; });
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 * 
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  void doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, Consumer runnable) {
		doWithThreadLocal(threadLocal, factory, (ThrowingConsumer) runnable::accept);
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 *
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  void doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, ThrowingConsumer runnable) 
			throws E {
		doWithThreadLocal(threadLocal, factory, (ThrowingFunction) t -> { runnable.accept(t); return null; });
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 *
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  O doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, Supplier runnable) {
		return doWithThreadLocal(threadLocal, factory, (ThrowingSupplier) runnable::get);
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 *
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  O doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, ThrowingSupplier runnable) 
			throws E {
		return doWithThreadLocal(threadLocal, factory, (ThrowingFunction) t -> runnable.get());
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 *
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  O doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, Function runnable) {
		return doWithThreadLocal(threadLocal, factory, (ThrowingFunction) runnable::apply);
	}
	
	/**
	 * Runs some code with a {@link ThreadLocal} and cleans it afterwards by removing the instance of the {@link ThreadLocal}
	 * through {@link ThreadLocal#remove()}.
	 *
	 * @param threadLocal the {@link ThreadLocal} to be used
	 * @param factory the supplier of the instance assigned to {@link ThreadLocal}
	 * @param runnable some code to be run
	 * @param  type of bean assigned to the ThreadLocal
	 * @see AutoRemoveThreadLocal
	 */
	public static  O doWithThreadLocal(ThreadLocal threadLocal, Supplier factory, ThrowingFunction runnable)
			throws E {
		T value = threadLocal.get();
		if (value == null) {
			value = factory.get();
			threadLocal.set(value);
		}
		
		try (AutoRemoveThreadLocal ignored = new AutoRemoveThreadLocal<>(threadLocal)) {
			return runnable.apply(value);
		}
	}
	
	/**
	 * A {@link ThreadLocal} that will be cleared ({@link ThreadLocal#remove()} method called) after usage as a try-with-resource.
	 */
	public static class AutoRemoveThreadLocal implements AutoCloseable, Supplier, Hanger {
		
		private final ThreadLocal surrogate;
		
		public AutoRemoveThreadLocal(ThreadLocal surrogate) {
			this.surrogate = surrogate;
		}
		
		@Override
		public T get() {
			return surrogate.get();
		}
		
		@Override
		public void set(T value) {
			surrogate.set(value);
		}
		
		@Override
		public void close() {
			surrogate.remove();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy