diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.kt b/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.kt index c1c8fac18..378a98893 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.kt +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.kt @@ -1,23 +1,21 @@ -package fr.free.nrw.commons.concurrency; +package fr.free.nrw.commons.concurrency -import androidx.annotation.NonNull; +import fr.free.nrw.commons.BuildConfig -import fr.free.nrw.commons.BuildConfig; -public class BackgroundPoolExceptionHandler implements ExceptionHandler { +class BackgroundPoolExceptionHandler : ExceptionHandler { /** * If an exception occurs on a background thread, this handler will crash for debug builds * but fail silently for release builds. * @param t */ - @Override - public void onException(@NonNull final Throwable t) { - //Crash for debug build + override fun onException(t: Throwable) { + // Crash for debug build if (BuildConfig.DEBUG) { - Thread thread = new Thread(() -> { - throw new RuntimeException(t); - }); - thread.start(); + val thread = Thread { + throw RuntimeException(t) + } + thread.start() } } } diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt b/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt index 80931b1c1..0efe057f2 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt @@ -1,39 +1,40 @@ -package fr.free.nrw.commons.concurrency; +package fr.free.nrw.commons.concurrency -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; +import java.util.concurrent.CancellationException +import java.util.concurrent.ExecutionException +import java.util.concurrent.Future +import java.util.concurrent.ScheduledThreadPoolExecutor +import java.util.concurrent.ThreadFactory -class ExceptionAwareThreadPoolExecutor extends ScheduledThreadPoolExecutor { - private final ExceptionHandler exceptionHandler; +class ExceptionAwareThreadPoolExecutor( + corePoolSize: Int, + threadFactory: ThreadFactory, + private val exceptionHandler: ExceptionHandler? +) : ScheduledThreadPoolExecutor(corePoolSize, threadFactory) { - public ExceptionAwareThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, - ExceptionHandler exceptionHandler) { - super(corePoolSize, threadFactory); - this.exceptionHandler = exceptionHandler; - } + override fun afterExecute(r: Runnable, t: Throwable?) { + super.afterExecute(r, t) + var throwable = t - @Override - protected void afterExecute(Runnable r, Throwable t) { - super.afterExecute(r, t); - if (t == null && r instanceof Future) { + if (throwable == null && r is Future<*>) { try { - Future future = (Future) r; - if (future.isDone()) future.get(); - } catch (CancellationException | InterruptedException e) { - //ignore - } catch (ExecutionException e) { - t = e.getCause() != null ? e.getCause() : e; - } catch (Exception e) { - t = e; + if (r.isDone) { + r.get() + } + } catch (e: CancellationException) { + // ignore + } catch (e: InterruptedException) { + // ignore + } catch (e: ExecutionException) { + throwable = e.cause ?: e + } catch (e: Exception) { + throwable = e } } - if (t != null) { - exceptionHandler.onException(t); + throwable?.let { + exceptionHandler?.onException(it) } } -} +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionHandler.kt b/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionHandler.kt index 38690305a..6b3d2a0f7 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionHandler.kt +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionHandler.kt @@ -1,7 +1,7 @@ -package fr.free.nrw.commons.concurrency; +package fr.free.nrw.commons.concurrency -import androidx.annotation.NonNull; +interface ExceptionHandler { -public interface ExceptionHandler { - void onException(@NonNull Throwable t); -} + fun onException(t: Throwable) + +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolService.kt b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolService.kt index f057f61b2..46138d676 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolService.kt +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolService.kt @@ -1,13 +1,12 @@ -package fr.free.nrw.commons.concurrency; +package fr.free.nrw.commons.concurrency -import androidx.annotation.NonNull; +import java.util.concurrent.Callable +import java.util.concurrent.Executor +import java.util.concurrent.ScheduledFuture +import java.util.concurrent.ScheduledThreadPoolExecutor +import java.util.concurrent.ThreadFactory +import java.util.concurrent.TimeUnit -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; /** * This class is a thread pool which provides some additional features: @@ -15,110 +14,109 @@ import java.util.concurrent.TimeUnit; * supply your own priority * - it gives you a way to handle exceptions thrown in the thread pool */ +class ThreadPoolService private constructor(builder: Builder) : Executor { + private val backgroundPool: ScheduledThreadPoolExecutor = ExceptionAwareThreadPoolExecutor( + builder.poolSize, + object : ThreadFactory { + private var count = 0 + override fun newThread(r: Runnable): Thread { + count++ + val t = Thread(r, "${builder.name}-$count") + // If the priority is specified out of range, we set the thread priority to + // Thread.MIN_PRIORITY + // It's done to prevent IllegalArgumentException and to prevent setting of + // improper high priority for a less priority task + t.priority = + if ( + builder.priority > Thread.MAX_PRIORITY + || + builder.priority < Thread.MIN_PRIORITY + ) { + Thread.MIN_PRIORITY + } else { + builder.priority + } + return t + } + }, + builder.exceptionHandler + ) -public class ThreadPoolService implements Executor { - private final ScheduledThreadPoolExecutor backgroundPool; - - private ThreadPoolService(final Builder b) { - backgroundPool = new ExceptionAwareThreadPoolExecutor(b.poolSize, - new ThreadFactory() { - int count = 0; - @Override - public Thread newThread(@NonNull Runnable r) { - count++; - Thread t = new Thread(r, String.format("%s-%s", b.name, count)); - //If the priority is specified out of range, we set the thread priority to Thread.MIN_PRIORITY - //It's done prevent IllegalArgumentException and to prevent setting of improper high priority for a less priority task - t.setPriority(b.priority > Thread.MAX_PRIORITY || b.priority < Thread.MIN_PRIORITY ? - Thread.MIN_PRIORITY : b.priority); - return t; - } - }, b.exceptionHandler); + fun schedule(callable: Callable, time: Long, timeUnit: TimeUnit): ScheduledFuture { + return backgroundPool.schedule(callable, time, timeUnit) } - public ScheduledFuture schedule(Callable callable, long time, TimeUnit timeUnit) { - return backgroundPool.schedule(callable, time, timeUnit); + fun schedule(runnable: Runnable): ScheduledFuture<*> { + return schedule(runnable, 0, TimeUnit.SECONDS) } - public ScheduledFuture schedule(Runnable runnable) { - return schedule(runnable, 0, TimeUnit.SECONDS); + fun schedule(runnable: Runnable, time: Long, timeUnit: TimeUnit): ScheduledFuture<*> { + return backgroundPool.schedule(runnable, time, timeUnit) } - public ScheduledFuture schedule(Runnable runnable, long time, TimeUnit timeUnit) { - return backgroundPool.schedule(runnable, time, timeUnit); + fun scheduleAtFixedRate( + task: Runnable, + initialDelay: Long, + period: Long, + timeUnit: TimeUnit + ): ScheduledFuture<*> { + return backgroundPool.scheduleWithFixedDelay(task, initialDelay, period, timeUnit) } - public ScheduledFuture scheduleAtFixedRate(final Runnable task, long initialDelay, - long period, final TimeUnit timeUnit) { - return backgroundPool.scheduleAtFixedRate(task, initialDelay, period, timeUnit); + fun executor(): ScheduledThreadPoolExecutor { + return backgroundPool } - public ScheduledThreadPoolExecutor executor() { - return backgroundPool; + fun shutdown() { + backgroundPool.shutdown() } - public void shutdown(){ - backgroundPool.shutdown(); - } - - @Override - public void execute(Runnable command) { - backgroundPool.execute(command); + override fun execute(command: Runnable) { + backgroundPool.execute(command) } /** - * Builder class for {@link ThreadPoolService} + * Builder class for [ThreadPoolService] */ - public static class Builder { - //Required - private final String name; - - //Optional - private int poolSize = 1; - private int priority = Thread.MIN_PRIORITY; - private ExceptionHandler exceptionHandler = null; - - /** - * @param name the name of the threads in the service. if there are N threads, - * the thread names will be like name-1, name-2, name-3,...,name-N - */ - public Builder(@NonNull String name) { - this.name = name; - } + class Builder(val name: String) { + var poolSize: Int = 1 + var priority: Int = Thread.MIN_PRIORITY + var exceptionHandler: ExceptionHandler? = null /** * @param poolSize the number of threads to keep in the pool - * @throws IllegalArgumentException if size of pool <=0 + * @throws IllegalArgumentException if size of pool <= 0 */ - public Builder setPoolSize(int poolSize) throws IllegalArgumentException { + fun setPoolSize(poolSize: Int): Builder { if (poolSize <= 0) { - throw new IllegalArgumentException("Pool size must be grater than 0"); + throw IllegalArgumentException("Pool size must be greater than 0") } - this.poolSize = poolSize; - return this; + this.poolSize = poolSize + return this } /** * @param priority Priority of the threads in the service. You can supply a constant from - * {@link java.lang.Thread} or - * specify your own priority in the range 1(MIN_PRIORITY) to 10(MAX_PRIORITY) - * By default, the priority is set to {@link java.lang.Thread#MIN_PRIORITY} + * [java.lang.Thread] or + * specify your own priority in the range 1(MIN_PRIORITY) + * to 10(MAX_PRIORITY) + * By default, the priority is set to [java.lang.Thread.MIN_PRIORITY] */ - public Builder setPriority(int priority) { - this.priority = priority; - return this; + fun setPriority(priority: Int): Builder { + this.priority = priority + return this } /** * @param handler The handler to use to handle exceptions in the service */ - public Builder setExceptionHandler(ExceptionHandler handler) { - this.exceptionHandler = handler; - return this; + fun setExceptionHandler(handler: ExceptionHandler): Builder { + exceptionHandler = handler + return this } - public ThreadPoolService build() { - return new ThreadPoolService(this); + fun build(): ThreadPoolService { + return ThreadPoolService(this) } } -} +} \ No newline at end of file