Cleanup concurrent
This commit is contained in:
committed by
Andrey Breslav
parent
3ab1901f06
commit
c074b4317e
@@ -1,47 +1,43 @@
|
|||||||
package kotlin.concurrent
|
package kotlin.concurrent
|
||||||
|
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
import java.util.concurrent.locks.ReadWriteLock
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock
|
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import kotlin.InlineOption.ONLY_LOCAL_RETURN
|
import kotlin.InlineOption.ONLY_LOCAL_RETURN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Executes given calculation under lock
|
* Executes given calculation under lock
|
||||||
Returns result of the calculation
|
* Returns result of the calculation
|
||||||
*/
|
*/
|
||||||
public inline fun <T> Lock.withLock([inlineOptions(ONLY_LOCAL_RETURN)] action: () -> T): T {
|
public inline fun <T> Lock.withLock([inlineOptions(ONLY_LOCAL_RETURN)] action: () -> T): T {
|
||||||
lock()
|
lock()
|
||||||
try {
|
try {
|
||||||
return action()
|
return action()
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Executes given calculation under read lock
|
* Executes given calculation under read lock
|
||||||
Returns result of the calculation
|
* Returns result of the calculation
|
||||||
*/
|
*/
|
||||||
public inline fun <T> ReentrantReadWriteLock.read([inlineOptions(ONLY_LOCAL_RETURN)] action: () -> T): T {
|
public inline fun <T> ReentrantReadWriteLock.read([inlineOptions(ONLY_LOCAL_RETURN)] action: () -> T): T {
|
||||||
val rl = readLock()
|
val rl = readLock()
|
||||||
rl.lock()
|
rl.lock()
|
||||||
try {
|
try {
|
||||||
return action()
|
return action()
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
rl.unlock()
|
rl.unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Executes given calculation under write lock.
|
* Executes given calculation under write lock.
|
||||||
The method does upgrade from read to write lock if needed
|
* The method does upgrade from read to write lock if needed
|
||||||
If such write has been initiated by checking some condition, the condition must be rechecked inside the action to avoid possible races
|
* If such write has been initiated by checking some condition, the condition must be rechecked inside the action to avoid possible races
|
||||||
Returns result of the calculation
|
* Returns result of the calculation
|
||||||
*/
|
*/
|
||||||
public inline fun <T> ReentrantReadWriteLock.write([inlineOptions(ONLY_LOCAL_RETURN)] action: () -> T): T {
|
public inline fun <T> ReentrantReadWriteLock.write([inlineOptions(ONLY_LOCAL_RETURN)] action: () -> T): T {
|
||||||
val rl = readLock()
|
val rl = readLock()
|
||||||
|
|
||||||
@@ -52,20 +48,19 @@ public inline fun <T> ReentrantReadWriteLock.write([inlineOptions(ONLY_LOCAL_RET
|
|||||||
wl.lock()
|
wl.lock()
|
||||||
try {
|
try {
|
||||||
return action()
|
return action()
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
readCount times { rl.lock() }
|
readCount times { rl.lock() }
|
||||||
wl.unlock()
|
wl.unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Execute given calculation and await for CountDownLatch
|
* Execute given calculation and await for CountDownLatch
|
||||||
Returns result of the calculation
|
* Returns result of the calculation
|
||||||
*/
|
*/
|
||||||
public fun <T> Int.latch(op: CountDownLatch.() -> T): T {
|
public fun <T> Int.latch(operation: CountDownLatch.() -> T): T {
|
||||||
val cdl = CountDownLatch(this)
|
val latch = CountDownLatch(this)
|
||||||
val res = cdl.op()
|
val result = latch.operation()
|
||||||
cdl.await()
|
latch.await()
|
||||||
return res
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,36 @@
|
|||||||
package kotlin.concurrent
|
package kotlin.concurrent
|
||||||
|
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.*
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.Future
|
|
||||||
import java.util.concurrent.Callable
|
|
||||||
|
|
||||||
public val currentThread: Thread
|
public val currentThread: Thread
|
||||||
get() = Thread.currentThread()
|
get() = Thread.currentThread()
|
||||||
|
|
||||||
public var Thread.name: String
|
public var Thread.name: String
|
||||||
get() = getName()
|
get() = getName()
|
||||||
set(name: String) { setName(name) }
|
set(value) {
|
||||||
|
setName(value)
|
||||||
|
}
|
||||||
|
|
||||||
public var Thread.daemon: Boolean
|
public var Thread.daemon: Boolean
|
||||||
get() = isDaemon()
|
get() = isDaemon()
|
||||||
set(on: Boolean) { setDaemon(on) }
|
set(value) {
|
||||||
|
setDaemon(value)
|
||||||
|
}
|
||||||
|
|
||||||
public val Thread.alive: Boolean
|
public val Thread.alive: Boolean
|
||||||
get() = isAlive()
|
get() = isAlive()
|
||||||
|
|
||||||
public var Thread.priority: Int
|
public var Thread.priority: Int
|
||||||
get() = getPriority()
|
get() = getPriority()
|
||||||
set(prio: Int) { setPriority(prio) }
|
set(value) {
|
||||||
|
setPriority(value)
|
||||||
|
}
|
||||||
|
|
||||||
public var Thread.contextClassLoader: ClassLoader?
|
public var Thread.contextClassLoader: ClassLoader?
|
||||||
get() = getContextClassLoader()
|
get() = getContextClassLoader()
|
||||||
set(loader: ClassLoader?) { setContextClassLoader(loader) }
|
set(value) {
|
||||||
|
setContextClassLoader(value)
|
||||||
|
}
|
||||||
|
|
||||||
public fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLoader: ClassLoader? = null, name: String? = null, priority: Int = -1, block: () -> Unit): Thread {
|
public fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLoader: ClassLoader? = null, name: String? = null, priority: Int = -1, block: () -> Unit): Thread {
|
||||||
val thread = object : Thread() {
|
val thread = object : Thread() {
|
||||||
@@ -50,14 +55,14 @@ public fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLo
|
|||||||
* Allows you to use the executor as a function to
|
* Allows you to use the executor as a function to
|
||||||
* execute the given block on the [[Executor]].
|
* execute the given block on the [[Executor]].
|
||||||
*/
|
*/
|
||||||
public /*inline*/ fun Executor.invoke(action: () -> Unit) {
|
public fun Executor.invoke(action: () -> Unit) {
|
||||||
execute(runnable(action))
|
execute(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows you to use the executor as a function to
|
* Allows you to use the executor as a function to
|
||||||
* execute the given block on the [[Executor]].
|
* execute the given block on the [[Executor]].
|
||||||
*/
|
*/
|
||||||
public /*inline*/ fun <T>ExecutorService.invoke(action: () -> T): Future<T> {
|
public fun <T> ExecutorService.invoke(action: () -> T): Future<T> {
|
||||||
return submit(action)
|
return submit(action)
|
||||||
}
|
}
|
||||||
@@ -4,67 +4,67 @@ import java.util.Timer
|
|||||||
import java.util.TimerTask
|
import java.util.TimerTask
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
public fun Timer.schedule(delay: Long, action: TimerTask.()->Unit) : TimerTask {
|
public fun Timer.schedule(delay: Long, action: TimerTask.() -> Unit): TimerTask {
|
||||||
val task = timerTask(action)
|
val task = timerTask(action)
|
||||||
schedule(task, delay)
|
schedule(task, delay)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Timer.schedule(time: Date, action: TimerTask.()->Unit) : TimerTask {
|
public fun Timer.schedule(time: Date, action: TimerTask.() -> Unit): TimerTask {
|
||||||
val task = timerTask(action)
|
val task = timerTask(action)
|
||||||
schedule(task, time)
|
schedule(task, time)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Timer.schedule(delay: Long, period: Long, action: TimerTask.()->Unit) : TimerTask {
|
public fun Timer.schedule(delay: Long, period: Long, action: TimerTask.() -> Unit): TimerTask {
|
||||||
val task = timerTask(action)
|
val task = timerTask(action)
|
||||||
schedule(task, delay, period)
|
schedule(task, delay, period)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Timer.schedule(time: Date, period: Long, action: TimerTask.()->Unit) : TimerTask {
|
public fun Timer.schedule(time: Date, period: Long, action: TimerTask.() -> Unit): TimerTask {
|
||||||
val task = timerTask(action)
|
val task = timerTask(action)
|
||||||
schedule(task, time, period)
|
schedule(task, time, period)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Timer.scheduleAtFixedRate(delay: Long, period: Long, action: TimerTask.()->Unit) : TimerTask {
|
public fun Timer.scheduleAtFixedRate(delay: Long, period: Long, action: TimerTask.() -> Unit): TimerTask {
|
||||||
val task = timerTask(action)
|
val task = timerTask(action)
|
||||||
scheduleAtFixedRate(task, delay, period)
|
scheduleAtFixedRate(task, delay, period)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Timer.scheduleAtFixedRate(time: Date, period: Long, action: TimerTask.()->Unit) : TimerTask {
|
public fun Timer.scheduleAtFixedRate(time: Date, period: Long, action: TimerTask.() -> Unit): TimerTask {
|
||||||
val task = timerTask(action)
|
val task = timerTask(action)
|
||||||
scheduleAtFixedRate(task, time, period)
|
scheduleAtFixedRate(task, time, period)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun timer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.()->Unit) : Timer {
|
public fun timer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.() -> Unit): Timer {
|
||||||
val timer = if(name == null) Timer(daemon) else Timer(name, daemon)
|
val timer = if (name == null) Timer(daemon) else Timer(name, daemon)
|
||||||
timer.schedule(initialDelay, period, action)
|
timer.schedule(initialDelay, period, action)
|
||||||
return timer
|
return timer
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun timer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, action: TimerTask.()->Unit) : Timer {
|
public fun timer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, action: TimerTask.() -> Unit): Timer {
|
||||||
val timer = if(name == null) Timer(daemon) else Timer(name, daemon)
|
val timer = if (name == null) Timer(daemon) else Timer(name, daemon)
|
||||||
timer.schedule(startAt, period, action)
|
timer.schedule(startAt, period, action)
|
||||||
return timer
|
return timer
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun fixedRateTimer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.()->Unit) : Timer {
|
public fun fixedRateTimer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.() -> Unit): Timer {
|
||||||
val timer = if(name == null) Timer(daemon) else Timer(name, daemon)
|
val timer = if (name == null) Timer(daemon) else Timer(name, daemon)
|
||||||
timer.scheduleAtFixedRate(initialDelay, period, action)
|
timer.scheduleAtFixedRate(initialDelay, period, action)
|
||||||
return timer
|
return timer
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun fixedRateTimer(name: String? = null, daemon: Boolean = false, startAt: Date, period : Long, action: TimerTask.()->Unit) : Timer {
|
public fun fixedRateTimer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, action: TimerTask.() -> Unit): Timer {
|
||||||
val timer = if(name == null) Timer(daemon) else Timer(name, daemon)
|
val timer = if (name == null) Timer(daemon) else Timer(name, daemon)
|
||||||
timer.scheduleAtFixedRate(startAt, period, action)
|
timer.scheduleAtFixedRate(startAt, period, action)
|
||||||
return timer
|
return timer
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun timerTask(action: TimerTask.()->Unit) : TimerTask = object: TimerTask() {
|
public fun timerTask(action: TimerTask.() -> Unit): TimerTask = object : TimerTask() {
|
||||||
public override fun run() {
|
public override fun run() {
|
||||||
action()
|
action()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,23 +12,15 @@ class TimerTest {
|
|||||||
test fun scheduledTask() {
|
test fun scheduledTask() {
|
||||||
val counter = AtomicInteger(0)
|
val counter = AtomicInteger(0)
|
||||||
val timer = Timer()
|
val timer = Timer()
|
||||||
/*
|
|
||||||
TODO this generates a compiler error!
|
|
||||||
|
|
||||||
val task = timer.scheduleAtFixedRate(1000, 1000) {
|
val task = timer.scheduleAtFixedRate(1000, 100) {
|
||||||
val current = counter.incrementAndGet()
|
val current = counter.incrementAndGet()
|
||||||
println("Timer fired at $current")
|
println("Timer fired at $current")
|
||||||
}
|
}
|
||||||
*/
|
Thread.sleep(1500)
|
||||||
val task = timerTask {
|
|
||||||
val current = counter.incrementAndGet()
|
|
||||||
println("Timer fired at $current")
|
|
||||||
}
|
|
||||||
timer.scheduleAtFixedRate(task, 1000, 1000)
|
|
||||||
Thread.sleep(5000)
|
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
|
||||||
val value = counter.get()
|
val value = counter.get()
|
||||||
assertTrue(value > 2, "current counter is $value")
|
assertTrue(value > 4, "current counter is $value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user