提交 15e1d082 编写于 作者: R rybalkinsd 提交者: oldratlee

1. clear naming for wrapTtl/unwrapTtl

2. TtlDelegate backing property unification
上级 99d5bc21
......@@ -3,19 +3,24 @@ package com.alibaba.ttl
import kotlin.reflect.KProperty
/**
* A shortcut method to instantiate [TransmittableThreadLocal].
*
* @since 2.11.0
*/
fun <T> ttl() = TransmittableThreadLocal<T?>()
/**
* Kotlin Delegate for immutable/mutable values or properties.
*
* @param backingProperty is [InheritableThreadLocal] if provided
* or [TransmittableThreadLocal] by default
*
* @since 2.11.0
*/
class TtlDelegate<T> {
private var _value = ttl<T>()
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? = _value.get()
class TtlDelegate<T>(private val backingProperty: InheritableThreadLocal<T?> = ttl()) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? = backingProperty.get()
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
_value.set(value)
backingProperty.set(value)
}
}
......@@ -2,6 +2,12 @@ package com.alibaba.ttl
import java.util.concurrent.Callable
/**
* Invoke operator for [TtlCallable].
*
* @since 2.11.0
*/
@Throws(Exception::class)
operator fun <V> TtlCallable<V>.invoke(): V = call()
......@@ -15,7 +21,7 @@ operator fun <V> TtlCallable<V>.invoke(): V = call()
*
* @since 2.11.0
*/
fun <V> Callable<V>.wrap(
fun <V> Callable<V>.wrapTtl(
releaseTtlValueReferenceAfterCall: Boolean = false,
idempotent: Boolean = false
): TtlCallable<V> = TtlCallable.get(this, releaseTtlValueReferenceAfterCall, idempotent)!!
......@@ -27,24 +33,24 @@ fun <V> Callable<V>.wrap(
* @param idempotent is idempotent or not. `true` will cover up bugs! **DO NOT** set, only when you know why.
* @return Wrapped list of [Callable]
*
* @see #Callable::wrap
* @see Callable.wrapTtl
* @since 2.11.0
*/
fun <V> List<Callable<V>>.wrap(
fun <V> List<Callable<V>>.wrapTtl(
releaseTtlValueReferenceAfterCall: Boolean = false,
idempotent: Boolean = false
): List<TtlCallable<V>> = map { it.wrap(releaseTtlValueReferenceAfterCall, idempotent) }
): List<TtlCallable<V>> = map { it.wrapTtl(releaseTtlValueReferenceAfterCall, idempotent) }
/**
* Extension function to unwrap [TtlCallable] to the original/underneath one.
* <p>
* if input `Callable` parameter is not a [TtlCallable] just return input `Callable`.
* if input [Callable] parameter is not a [TtlCallable] just return input [Callable].
* <p>
* so `callable.wrap().unwrap()` will always return the same input `callable` object.
* so `callable.wrapTtl().unwrapTtl()` will always return the same input [Callable] object.
*
* @since 2.11.0
*/
fun <V> Callable<V>.unwrap(): Callable<V> = when(this) {
fun <V> Callable<V>.unwrapTtl(): Callable<V> = when(this) {
is TtlCallable<V> -> getCallable()
else -> this
}
......@@ -52,10 +58,10 @@ fun <V> Callable<V>.unwrap(): Callable<V> = when(this) {
/**
* Extension function to unwrap [TtlCallable] to the original/underneath one.
* <p>
* Invoke [unwrap] for each element in collection.
* Invoke [unwrapTtl] for each element in collection.
* <p>
*
* @see #Callable::unwrap
* @see Callable.unwrapTtl
* @since 2.11.0
*/
fun <V> List<Callable<V>>.unwrap() : List<Callable<V>> = map { it.unwrap() }
fun <V> List<Callable<V>>.unwrapTtl() : List<Callable<V>> = map { it.unwrapTtl() }
......@@ -11,7 +11,7 @@ package com.alibaba.ttl
*
* @since 2.11.0
*/
fun Runnable.wrap(
fun Runnable.wrapTtl(
releaseTtlValueReferenceAfterRun: Boolean = false,
idempotent: Boolean = false
): TtlRunnable = TtlRunnable.get(this, releaseTtlValueReferenceAfterRun, idempotent)!!
......@@ -25,24 +25,24 @@ fun Runnable.wrap(
* **_Caution_**: `true` will cover up bugs! **DO NOT** set, only when you know why.
* @return Wrapped list of [Runnable]
*
* @see Runnable.wrap
* @see Runnable.wrapTtl
* @since 2.11.0
*/
fun List<Runnable>.wrap(
fun List<Runnable>.wrapTtl(
releaseTtlValueReferenceAfterRun: Boolean = false,
idempotent: Boolean = false
): List<TtlRunnable> = map { it.wrap(releaseTtlValueReferenceAfterRun, idempotent) }
): List<TtlRunnable> = map { it.wrapTtl(releaseTtlValueReferenceAfterRun, idempotent) }
/**
* Extension function to unwrap [TtlRunnable] to the original/underneath one.
* <p>
* if input `Runnable` parameter is not a [TtlRunnable] just return input `Runnable`.
* <p>
* so `Runnable.wrap().unwrap()` will always return the same input `Runnable` object.
* so `Runnable.wrapTtl().unwrapTtl()` will always return the same input `Runnable` object.
*
* @since 2.11.0
*/
fun Runnable.unwrap(): Runnable = when (this) {
fun Runnable.unwrapTtl(): Runnable = when (this) {
is TtlRunnable -> runnable
else -> this
}
......@@ -50,10 +50,10 @@ fun Runnable.unwrap(): Runnable = when (this) {
/**
* Extension function to unwrap [TtlRunnable] to the original/underneath one.
* <p>
* Invoke [Runnable.unwrap] for each element in collection.
* Invoke [Runnable.unwrapTtl] for each element in collection.
* <p>
*
* @see Runnable.unwrap
* @see Runnable.unwrapTtl
* @since 2.11.0
*/
fun List<Runnable>.unwrap(): List<Runnable> = map { it.unwrap() }
fun List<Runnable>.unwrapTtl(): List<Runnable> = map { it.unwrapTtl() }
......@@ -2,30 +2,49 @@ package com.alibaba.ttl
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertNull
import org.junit.Test
import kotlin.concurrent.thread
class TransmittableThreadLocalExtKtTest {
@Test
fun `ttl delegate`() {
fun `simple ttl delegate`() {
var parent by TtlDelegate<String>()
parent = "value-set-in-parent"
var valueFromParent: String? = null
thread {
val valueFromParent = parent
assertEquals("value-set-in-parent", valueFromParent)
valueFromParent = parent
}.join()
assertEquals("value-set-in-parent", valueFromParent)
}
@Test
fun `ttl nullable delegate`() {
val parent by TtlDelegate<Int>()
var result: Int? = null
thread {
result = parent
}.join()
assertNull(result)
}
@Test
fun `ttl inherited delegate`() {
val inheritedTtl = object : InheritableThreadLocal<Int?>() { }
var parent by TtlDelegate(inheritedTtl)
parent = 42
var result: Int? = null
thread {
assertNotNull("value-set-in-parent", parent)
result = parent
}.join()
assertNotNull(result)
}
}
......@@ -22,17 +22,17 @@ class TtlCallableExtKtTest {
val rule = ConditionalIgnoreRule()
@Test
fun `callable wrap extension function `() {
fun `callable wrapTtl extension function `() {
val call = Call("1")
val ttlCallable = call.wrap()
val ttlCallable = call.wrapTtl()
assertSame(call, ttlCallable.callable)
}
@Test
fun `callable wrap extension function multiple times`() {
val call = Call("1").wrap()
fun `callable wrapTtl extension function multiple times`() {
val call = Call("1").wrapTtl()
try {
call.wrap()
call.wrapTtl()
fail()
} catch (e: IllegalStateException) {
assertThat<String>(e.message, CoreMatchers.containsString("Already TtlCallable"))
......@@ -41,8 +41,8 @@ class TtlCallableExtKtTest {
}
@Test
fun `list of callable wrap extension function`() {
val callList = listOf(Call("1"), Call("2"), Call("3")).wrap()
fun `list of callable wrapTtl extension function`() {
val callList = listOf(Call("1"), Call("2"), Call("3")).wrapTtl()
assertEquals(3, callList.size)
callList.forEach {
......@@ -57,7 +57,7 @@ class TtlCallableExtKtTest {
val call = Call("1", ttlInstances)
val ttlCallable = call.wrap()
val ttlCallable = call.wrapTtl()
// create after new Task, won't see parent value in in task!
createParentTtlInstancesAfterCreateChild(ttlInstances)
......
......@@ -14,17 +14,17 @@ class TtlRunnableExtKtTest {
val rule = ConditionalIgnoreRule()
@Test
fun `runnable wrap extension function `() {
fun `runnable wrapTtl extension function `() {
val task = Task("1")
val ttlRunnable = task.wrap()
val ttlRunnable = task.wrapTtl()
Assert.assertSame(task, ttlRunnable.runnable)
}
@Test
fun `runnable wrap extension function multiple times`() {
val task = Task("1").wrap()
fun `runnable wrapTtl extension function multiple times`() {
val task = Task("1").wrapTtl()
try {
task.wrap()
task.wrapTtl()
Assert.fail()
} catch (e: IllegalStateException) {
Assert.assertThat<String>(e.message, CoreMatchers.containsString("Already TtlRunnable"))
......@@ -33,8 +33,8 @@ class TtlRunnableExtKtTest {
}
@Test
fun `list of runnable wrap extension function`() {
val taskList = listOf(Task("1"), Task("2"), Task("3")).wrap()
fun `list of runnable wrapTtl extension function`() {
val taskList = listOf(Task("1"), Task("2"), Task("3")).wrapTtl()
Assert.assertEquals(3, taskList.size)
taskList.forEach {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册