Skip to content

Commit 87a453c

Browse files
authored
Migrated concurrency module from Java to Kotiln (commons-app#6110)
* Rename .java to .kt * Migrated concurrency module to Kotlin
1 parent fdbe504 commit 87a453c

8 files changed

+190
-193
lines changed

app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java

-23
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package fr.free.nrw.commons.concurrency
2+
3+
import fr.free.nrw.commons.BuildConfig
4+
5+
6+
class BackgroundPoolExceptionHandler : ExceptionHandler {
7+
/**
8+
* If an exception occurs on a background thread, this handler will crash for debug builds
9+
* but fail silently for release builds.
10+
* @param t
11+
*/
12+
override fun onException(t: Throwable) {
13+
// Crash for debug build
14+
if (BuildConfig.DEBUG) {
15+
val thread = Thread {
16+
throw RuntimeException(t)
17+
}
18+
thread.start()
19+
}
20+
}
21+
}

app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.java

-39
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package fr.free.nrw.commons.concurrency
2+
3+
import java.util.concurrent.CancellationException
4+
import java.util.concurrent.ExecutionException
5+
import java.util.concurrent.Future
6+
import java.util.concurrent.ScheduledThreadPoolExecutor
7+
import java.util.concurrent.ThreadFactory
8+
9+
10+
class ExceptionAwareThreadPoolExecutor(
11+
corePoolSize: Int,
12+
threadFactory: ThreadFactory,
13+
private val exceptionHandler: ExceptionHandler?
14+
) : ScheduledThreadPoolExecutor(corePoolSize, threadFactory) {
15+
16+
override fun afterExecute(r: Runnable, t: Throwable?) {
17+
super.afterExecute(r, t)
18+
var throwable = t
19+
20+
if (throwable == null && r is Future<*>) {
21+
try {
22+
if (r.isDone) {
23+
r.get()
24+
}
25+
} catch (e: CancellationException) {
26+
// ignore
27+
} catch (e: InterruptedException) {
28+
// ignore
29+
} catch (e: ExecutionException) {
30+
throwable = e.cause ?: e
31+
} catch (e: Exception) {
32+
throwable = e
33+
}
34+
}
35+
36+
throwable?.let {
37+
exceptionHandler?.onException(it)
38+
}
39+
}
40+
}

app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionHandler.java

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package fr.free.nrw.commons.concurrency
2+
3+
interface ExceptionHandler {
4+
5+
fun onException(t: Throwable)
6+
7+
}

app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolService.java

-124
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package fr.free.nrw.commons.concurrency
2+
3+
import java.util.concurrent.Callable
4+
import java.util.concurrent.Executor
5+
import java.util.concurrent.ScheduledFuture
6+
import java.util.concurrent.ScheduledThreadPoolExecutor
7+
import java.util.concurrent.ThreadFactory
8+
import java.util.concurrent.TimeUnit
9+
10+
11+
/**
12+
* This class is a thread pool which provides some additional features:
13+
* - it sets the thread priority to a value lower than foreground priority by default, or you can
14+
* supply your own priority
15+
* - it gives you a way to handle exceptions thrown in the thread pool
16+
*/
17+
class ThreadPoolService private constructor(builder: Builder) : Executor {
18+
private val backgroundPool: ScheduledThreadPoolExecutor = ExceptionAwareThreadPoolExecutor(
19+
builder.poolSize,
20+
object : ThreadFactory {
21+
private var count = 0
22+
override fun newThread(r: Runnable): Thread {
23+
count++
24+
val t = Thread(r, "${builder.name}-$count")
25+
// If the priority is specified out of range, we set the thread priority to
26+
// Thread.MIN_PRIORITY
27+
// It's done to prevent IllegalArgumentException and to prevent setting of
28+
// improper high priority for a less priority task
29+
t.priority =
30+
if (
31+
builder.priority > Thread.MAX_PRIORITY
32+
||
33+
builder.priority < Thread.MIN_PRIORITY
34+
) {
35+
Thread.MIN_PRIORITY
36+
} else {
37+
builder.priority
38+
}
39+
return t
40+
}
41+
},
42+
builder.exceptionHandler
43+
)
44+
45+
fun <V> schedule(callable: Callable<V>, time: Long, timeUnit: TimeUnit): ScheduledFuture<V> {
46+
return backgroundPool.schedule(callable, time, timeUnit)
47+
}
48+
49+
fun schedule(runnable: Runnable): ScheduledFuture<*> {
50+
return schedule(runnable, 0, TimeUnit.SECONDS)
51+
}
52+
53+
fun schedule(runnable: Runnable, time: Long, timeUnit: TimeUnit): ScheduledFuture<*> {
54+
return backgroundPool.schedule(runnable, time, timeUnit)
55+
}
56+
57+
fun scheduleAtFixedRate(
58+
task: Runnable,
59+
initialDelay: Long,
60+
period: Long,
61+
timeUnit: TimeUnit
62+
): ScheduledFuture<*> {
63+
return backgroundPool.scheduleWithFixedDelay(task, initialDelay, period, timeUnit)
64+
}
65+
66+
fun executor(): ScheduledThreadPoolExecutor {
67+
return backgroundPool
68+
}
69+
70+
fun shutdown() {
71+
backgroundPool.shutdown()
72+
}
73+
74+
override fun execute(command: Runnable) {
75+
backgroundPool.execute(command)
76+
}
77+
78+
/**
79+
* Builder class for [ThreadPoolService]
80+
*/
81+
class Builder(val name: String) {
82+
var poolSize: Int = 1
83+
var priority: Int = Thread.MIN_PRIORITY
84+
var exceptionHandler: ExceptionHandler? = null
85+
86+
/**
87+
* @param poolSize the number of threads to keep in the pool
88+
* @throws IllegalArgumentException if size of pool <= 0
89+
*/
90+
fun setPoolSize(poolSize: Int): Builder {
91+
if (poolSize <= 0) {
92+
throw IllegalArgumentException("Pool size must be greater than 0")
93+
}
94+
this.poolSize = poolSize
95+
return this
96+
}
97+
98+
/**
99+
* @param priority Priority of the threads in the service. You can supply a constant from
100+
* [java.lang.Thread] or
101+
* specify your own priority in the range 1(MIN_PRIORITY)
102+
* to 10(MAX_PRIORITY)
103+
* By default, the priority is set to [java.lang.Thread.MIN_PRIORITY]
104+
*/
105+
fun setPriority(priority: Int): Builder {
106+
this.priority = priority
107+
return this
108+
}
109+
110+
/**
111+
* @param handler The handler to use to handle exceptions in the service
112+
*/
113+
fun setExceptionHandler(handler: ExceptionHandler): Builder {
114+
exceptionHandler = handler
115+
return this
116+
}
117+
118+
fun build(): ThreadPoolService {
119+
return ThreadPoolService(this)
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)