Moved ThreadBox into core.internal

This commit is contained in:
Shams Asari
2017-07-21 12:44:58 +01:00
parent 08d2e351d2
commit a485bbada8
19 changed files with 52 additions and 47 deletions

View File

@ -25,12 +25,10 @@ import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock
import java.util.zip.Deflater
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
import kotlin.concurrent.withLock
// TODO: Review by EOY2016 if we ever found these utilities helpful.
val Int.bd: BigDecimal get() = BigDecimal(this)
@ -163,33 +161,6 @@ fun <T> logElapsedTime(label: String, logger: Logger? = null, body: () -> T): T
fun <T> Logger.logElapsedTime(label: String, body: () -> T): T = logElapsedTime(label, this, body)
/**
* A threadbox is a simple utility that makes it harder to forget to take a lock before accessing some shared state.
* Simply define a private class to hold the data that must be grouped under the same lock, and then pass the only
* instance to the ThreadBox constructor. You can now use the [locked] method with a lambda to take the lock in a
* way that ensures it'll be released if there's an exception.
*
* Note that this technique is not infallible: if you capture a reference to the fields in another lambda which then
* gets stored and invoked later, there may still be unsafe multi-threaded access going on, so watch out for that.
* This is just a simple guard rail that makes it harder to slip up.
*
* Example:
*
* private class MutableState { var i = 5 }
* private val state = ThreadBox(MutableState())
*
* val ii = state.locked { i }
*/
class ThreadBox<out T>(val content: T, val lock: ReentrantLock = ReentrantLock()) {
inline fun <R> locked(body: T.() -> R): R = lock.withLock { body(content) }
inline fun <R> alreadyLocked(body: T.() -> R): R {
check(lock.isHeldByCurrentThread, { "Expected $lock to already be locked." })
return body(content)
}
fun checkNotLocked() = check(!lock.isHeldByCurrentThread)
}
/**
* Given a path to a zip file, extracts it to the given directory.
*/

View File

@ -0,0 +1,32 @@
package net.corda.core.internal
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
/**
* A threadbox is a simple utility that makes it harder to forget to take a lock before accessing some shared state.
* Simply define a private class to hold the data that must be grouped under the same lock, and then pass the only
* instance to the ThreadBox constructor. You can now use the [locked] method with a lambda to take the lock in a
* way that ensures it'll be released if there's an exception.
*
* Note that this technique is not infallible: if you capture a reference to the fields in another lambda which then
* gets stored and invoked later, there may still be unsafe multi-threaded access going on, so watch out for that.
* This is just a simple guard rail that makes it harder to slip up.
*
* Example:
*```
* private class MutableState { var i = 5 }
* private val state = ThreadBox(MutableState())
*
* val ii = state.locked { i }
* ```
*/
class ThreadBox<out T>(val content: T, val lock: ReentrantLock = ReentrantLock()) {
inline fun <R> locked(body: T.() -> R): R = lock.withLock { body(content) }
inline fun <R> alreadyLocked(body: T.() -> R): R {
check(lock.isHeldByCurrentThread, { "Expected $lock to already be locked." })
return body(content)
}
fun checkNotLocked(): Unit = check(!lock.isHeldByCurrentThread)
}