Cleanup concurrent

This commit is contained in:
Ilya Ryzhenkov
2014-09-12 15:50:30 +04:00
committed by Andrey Breslav
parent 3ab1901f06
commit c074b4317e
4 changed files with 59 additions and 67 deletions
+22 -27
View File
@@ -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)
} }
+15 -15
View File
@@ -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()
} }
+3 -11
View File
@@ -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")
} }
} }