-
-
Save pablisco/6d4d5c3c132091a78a64ece885383b93 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlinx.coroutines.experimental.channels.Channel | |
import kotlinx.coroutines.experimental.launch | |
import kotlinx.coroutines.experimental.runBlocking | |
import org.junit.Assert.assertEquals | |
import org.junit.Test | |
import java.util.concurrent.SynchronousQueue | |
import kotlin.properties.Delegates | |
import kotlin.reflect.KProperty | |
class Scheduler { | |
fun schedule(f: () -> Unit) = Thread(f).apply { start() } | |
} | |
class FutureValue<A> { | |
private val queue by lazy { SynchronousQueue<A>() } | |
operator fun getValue(thisRef: Nothing?, property: KProperty<*>): A = | |
queue.take() | |
operator fun setValue(thisRef: Nothing?, property: KProperty<*>, value: A) = | |
queue.put(value) | |
} | |
fun <A> future() = FutureValue<A>() | |
class AsyncValue<A> { | |
private val channel by lazy { Channel<A>() } | |
operator fun getValue(thisRef: Nothing?, property: KProperty<*>): A = | |
runBlocking { channel.receive() } | |
operator fun setValue(thisRef: Nothing?, property: KProperty<*>, value: A) = | |
launch { channel.send(value) } | |
} | |
fun <A> async() = AsyncValue<A>() | |
fun Any.wait() = synchronized(this) { (this as Object).wait() } | |
fun Any.notify() = synchronized(this) { (this as Object).notify() } | |
class WaitNotifyValue<A> { | |
private var value: A? = null | |
operator fun getValue(thisRef: Nothing?, property: KProperty<*>): A { | |
wait() | |
return value!! | |
} | |
operator fun setValue(thisRef: Nothing?, property: KProperty<*>, value: A) { | |
this.value = value | |
notify() | |
} | |
} | |
fun <A> waitNotify() = WaitNotifyValue<A>() | |
private const val EXPECTED_VALUE = "expected value" | |
class ThreadTest { | |
@Test(expected = AssertionError::class) | |
fun failing() { | |
val scheduler = Scheduler() | |
var result: String? = null | |
scheduler.schedule { | |
result = EXPECTED_VALUE | |
} | |
assertEquals(result, EXPECTED_VALUE) | |
} | |
@Test | |
fun old_fashion() { | |
val scheduler = Scheduler() | |
var result: String? = null | |
scheduler.schedule { | |
result = EXPECTED_VALUE | |
notify() | |
} | |
wait() | |
assertEquals(result, EXPECTED_VALUE) | |
} | |
@Test | |
fun queue() { | |
val scheduler = Scheduler() | |
val queue = SynchronousQueue<String>() | |
scheduler.schedule { | |
queue.put(EXPECTED_VALUE) | |
} | |
assertEquals(queue.take(), EXPECTED_VALUE) | |
} | |
@Test | |
fun coroutines() { | |
runBlocking { | |
val scheduler = Scheduler() | |
val channel = Channel<String>() | |
scheduler.schedule { | |
launch { channel.send(EXPECTED_VALUE) } | |
} | |
assertEquals(channel.receive(), EXPECTED_VALUE) | |
} | |
} | |
@Test | |
fun delegate() { | |
val scheduler = Scheduler() | |
var result by future<String>() | |
scheduler.schedule { | |
result = EXPECTED_VALUE | |
} | |
assertEquals(result, EXPECTED_VALUE) | |
} | |
@Test | |
fun delegate_coroutines() { | |
val scheduler = Scheduler() | |
var result by async<String>() | |
scheduler.schedule { | |
result = EXPECTED_VALUE | |
} | |
assertEquals(result, EXPECTED_VALUE) | |
} | |
@Test | |
fun delegate_old_fashion() { | |
val scheduler = Scheduler() | |
var result by waitNotify<String>() | |
scheduler.schedule { | |
result = EXPECTED_VALUE | |
} | |
assertEquals(result, EXPECTED_VALUE) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment