Skip to content

Instantly share code, notes, and snippets.

@pablisco
Last active February 19, 2018 00:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pablisco/6d4d5c3c132091a78a64ece885383b93 to your computer and use it in GitHub Desktop.
Save pablisco/6d4d5c3c132091a78a64ece885383b93 to your computer and use it in GitHub Desktop.
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