SlideShare ist ein Scribd-Unternehmen logo
1 von 156
Downloaden Sie, um offline zu lesen
Kotlin	Coroutines	Reloaded
Presented	at	JVM	Language	Summit,	2017
/Roman	Elizarov	@	JetBrains
Speaker:	Roman	Elizarov
• 16+	years	experience
• Previously	developed	high-perf	trading	software	
@	Devexperts
• Teach	concurrent	&	distributed	programming	
@	St.	Petersburg	ITMO	University
• Chief	judge	
@	Northeastern	European	Region	of	ACM	ICPC	
• Now	work	on	Kotlin	
@	JetBrains
Agenda
• Recap	of	Kotlin	coroutines	prototype
• Presented	@	JVMLS,	2016	by	Andrey	Breslav
• The	issues	in	the	prototype	design
• and	the	solutions	that	were	found
• Design	released	to	public	in	Kotlin	1.1
• Evolved	coroutines	support	libraries
• Challenges	&	future	directions
Recap	of	Kotlin	coroutines	
prototype
Presented	@	JVMLS,	2016	by	Andrey	Breslav
Async	the	C#	(JS,	TS,	Dart,	etc)	way
async Task<String> Work() { … }
async Task MoreWork()
{
Console.WriteLine("Work started");
var str = await Work();
Console.WriteLine($"Work completed {str}");
}
Async	the	C#	(JS,	TS,	Dart,	etc)	way
async Task<String> work() { … }
async Task MoreWork()
{
Console.WriteLine("Work started");
var str = await Work();
Console.WriteLine($"Work completed {str}");
}
Async	the	Kotlin	way	(prototype)
fun work(): CompletableFuture<String> { … }
fun moreWork() = async {
println("Work started")
val str = await(work())
println("Work completed: $str")
}
Async	the	Kotlin	way	(prototype)
fun work(): CompletableFuture<String> { … }
fun moreWork() = async {
println("Work started")
val str = await(work())
println("Work completed: $str")
}
Functions	vs	Keywords
Extensibility
Runs	on	stock	JVM	1.6+
Purely	local	-- no	global	
bytecode	transforms
Suspending	functions
A	grand	unification	between	async/await	and	generate/yield
Suspending	functions:	use
val str = await(work())
Suspending	functions:	use
val str = await(work())
CompletableFuture<String>
// String result
Suspending	functions:	declare	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Unit
CompletableFuture<String>
// String result
Suspending	functions:	declare	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Unit
CompletableFuture<String>
callback void
// String result
Magic	signature	transformation
Suspending	functions:	declare	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Unit
CompletableFuture<String>
callback void
// String result
Continuation	is	a	generic	callback	interface
interface Continuation<in T> {
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Suspending	functions:	implement	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
CompletableFuture<String>
// String result
Suspending	functions:	implement	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
CompletableFuture<String>
// String result
Suspending	functions:	implement	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
CompletableFuture<String>
// String result
Suspending	functions:	implement	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
CompletableFuture<String>
// String result
Suspending	functions:	implement	(prototype)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
CompletableFuture<String>
// String result
Simple,	but	wrong!
A	problematic	example
Where	grand	vision	meets	reality
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
What	if	work()	always	returns	a	
future	that	is	already	complete?
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
await$lambda
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
await$lambda
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
await$lambda
ContinuationImpl.resume
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
await$lambda
ContinuationImpl.resume
problem$stateMachine
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
await$lambda
ContinuationImpl.resume
problem$stateMachine
await
A	problematic	example
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>) {
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun problem() = async {
repeat(10_000) {
await(work())
}
}
stack
problem$stateMachine
await
CompletableFuture.whenComplete
await$lambda
ContinuationImpl.resume
problem$stateMachine
await
…
StackOverflowError
A	solution
A	difference	between	knowing	the	path	&	walking	the	path.
A	solution
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Unit
CompletableFuture<String>
// String result
A	solution	(0):	stack	unwind	convention
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
CompletableFuture<String>
// String result
A	solution	(0)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
CompletableFuture<String>
// String result
T | COROUTINE_SUSPENDED
A	solution	(0)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
CompletableFuture<String>
// String result
T | COROUTINE_SUSPENDED
Did	not	suspend	->	Returns	result
A	solution	(0)
val str = await(work())
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
CompletableFuture<String>
// String result
T | COROUTINE_SUSPENDED
Did	not	suspend	->	Returns	result
Did	suspend	->	WILL	invoke	continuation
A	solution	(0)
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any? {
…
}
A	solution?
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any? {
val consensus = AtomicReference<Any?>(UNDECIDED)
f.whenComplete { value, exception ->
if (exception != null) {
if (!consensus.compareAndSet(UNDECIDED, Fail(exception)))
c.resumeWithException(exception)
} else {
if (!consensus.compareAndSet(UNDECIDED, value))
c.resume(value!!)
}
}
consensus.compareAndSet(UNDECIDED, COROUTINE_SUSPENDED)
val result = consensus.get()
if (result is Fail) throw result.exception
return result
}
A	solution?
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any? {
val consensus = AtomicReference<Any?>(UNDECIDED)
f.whenComplete { value, exception ->
if (exception != null) {
if (!consensus.compareAndSet(UNDECIDED, Fail(exception)))
c.resumeWithException(exception)
} else {
if (!consensus.compareAndSet(UNDECIDED, value))
c.resume(value!!)
}
}
consensus.compareAndSet(UNDECIDED, COROUTINE_SUSPENDED)
val result = consensus.get()
if (result is Fail) throw result.exception
return result
}
Wat?
A	solution	(1):	Call/declaration	fidelity
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
suspend fun <T> await(f: CompletableFuture<T>): T
natural	signature
A	solution	(1)
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
suspend fun <T> await(f: CompletableFuture<T>): T
Compiles	as	(on	JVM)
A	solution	(1)
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
suspend fun <T> await(f: CompletableFuture<T>): T
Compiles	as	(on	JVM)
CPS	Transformation
A	solution	(1)
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
suspend fun <T> await(f: CompletableFuture<T>)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
Recover	continuation
A	solution	(1)
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
suspend fun <T> await(f: CompletableFuture<T>)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
Inspired	by	call/cc	from	Scheme
Recover	continuation
A	solution	(1)
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any?
suspend fun <T> await(f: CompletableFuture<T>)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
Works	as
Inspired	by	call/cc	from	Scheme
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
inline suspend fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?): T
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
inline suspend fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?): T
T | COROUTINE_SUSPENDED
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
inline suspend fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?): T
Intrinsic
T | COROUTINE_SUSPENDED
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
inline suspend fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?): T
fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?,
c: Continuation<T>): Any? =
block(c)
Compiles	as	(on	JVM)
Intrinsic
CPS	Transformation
A	solution	(1)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
inline suspend fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?): T
fun <T> suspendCoroutineOrReturn(
crossinline block: (Continuation<T>) -> Any?,
c: Continuation<T>): Any? =
block(c)
Compiles	as	(on	JVM)
Intrinsic
CPS	Transformation
A	solution	(2):	Tail	suspension
A	solution	(2)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
Tail	suspend	invocation:
Continuation	pass-through
A	solution	(2)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any? =
suspendCoroutineOrReturn(c) { c ->
…
}
Tail	suspend	invocation:
Continuation	pass-through
Compiles	as	(on	JVM)
CPS	Transformation
A	solution	(2)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any? =
suspendCoroutineOrReturn(c) { c ->
…
}
Tail	suspend	invocation:
Continuation	pass-through
Compiles	as	(on	JVM)
CPS	Transformation
A	solution	(2)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutineOrReturn { c ->
…
}
fun <T> await(f: CompletableFuture<T>, c: Continuation<T>): Any? {
…
}
Tail	suspend	invocation:
Continuation	pass-through
Compiles	as	(on	JVM)
CPS	Transformation
A	solution	(3):	Abstraction
A	solution	(3)
public inline suspend fun <T> suspendCoroutine(
crossinline block: (Continuation<T>) -> Unit): T =
suspendCoroutineOrReturn { c: Continuation<T> ->
val safe = SafeContinuation(c)
block(safe)
safe.getResult()
}
A	solution	(3)
public inline suspend fun <T> suspendCoroutine(
crossinline block: (Continuation<T>) -> Unit): T =
suspendCoroutineOrReturn { c: Continuation<T> ->
val safe = SafeContinuation(c)
block(safe)
safe.getResult()
}
A	solution	(3)
public inline suspend fun <T> suspendCoroutine(
crossinline block: (Continuation<T>) -> Unit): T =
suspendCoroutineOrReturn { c: Continuation<T> ->
val safe = SafeContinuation(c)
block(safe)
safe.getResult()
}
Any?	Is	gone
A	solution	(3)
public inline suspend fun <T> suspendCoroutine(
crossinline block: (Continuation<T>) -> Unit): T =
suspendCoroutineOrReturn { c: Continuation<T> ->
val safe = SafeContinuation(c)
block(safe)
safe.getResult()
}
Encapsulates	result	
consensus	algorithm
A	solution	(4):	Putting	it	all	together
A	solution	(4)
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutine { c ->
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
Looks	simple,	works	correctly!
Recap	steps	to	solution
• T	|	COROUTINE_SUSPENDED	(Any?)	to	allow	invocations	that	
do	not	suspend	and	thus	avoid	StackOverflowError
• Call/declaration	fidelity	via	CPS	transformation
• Introduce	call/cc	(suspendCoroutineOrReturn)	to	recover	
hidden	continuation
• Tail	call	invocation	support	to	recover	prototype	semantics
• Use	abstraction	(suspendCoroutine)	to	hide	implementation	
complexities	from	end-users
The	final	touch:	await	extension
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutine { c ->
f.whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
The	final	touch:	await	extension
suspend fun <T> CompletableFuture<T>.await(): T =
suspendCoroutine { c ->
whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
The	final	touch:	await	extension
suspend fun <T> CompletableFuture<T>.await(): T =
suspendCoroutine { c ->
whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun moreWork() = async {
println("Work started")
val str = await(work())
println("Work completed: $str")
}
The	final	touch:	await	extension
suspend fun <T> CompletableFuture<T>.await(): T =
suspendCoroutine { c ->
whenComplete { value, exception ->
if (exception != null) c.resumeWithException(exception)
else c.resume(value!!)
}
}
fun moreWork() = async {
println("Work started")
val str = work().await()
println("Work completed: $str")
}
Reads	left-to-right	just	like	it	executes
Coroutine	builders
The	mystery	of	inception
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> {
val controller = FutureController<T>()
c(controller).resume(Unit)
return controller.future
}
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> {
val controller = FutureController<T>()
c(controller).resume(Unit)
return controller.future
}
A	special	modifier
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> {
val controller = FutureController<T>()
c(controller).resume(Unit)
return controller.future
}
Magic	signature	transformation
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> {
val controller = FutureController<T>()
c(controller).resume(Unit)
return controller.future
}
A	boilerplate	to	start	coroutine
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> { … }
class FutureController<T> {
val future = CompletableFuture<T>()
operator fun handleResult(value: T, c: Continuation<Nothing>) {
future.complete(value)
}
operator fun handleException(exception: Throwable,
c: Continuation<Nothing>) {
future.completeExceptionally(exception)
}
}
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> { … }
class FutureController<T> {
val future = CompletableFuture<T>()
operator fun handleResult(value: T, c: Continuation<Nothing>) {
future.complete(value)
}
operator fun handleException(exception: Throwable,
c: Continuation<Nothing>) {
future.completeExceptionally(exception)
}
}
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> { … }
class FutureController<T> {
val future = CompletableFuture<T>()
operator fun handleResult(value: T, c: Continuation<Nothing>) {
future.complete(value)
}
operator fun handleException(exception: Throwable,
c: Continuation<Nothing>) {
future.completeExceptionally(exception)
}
}
was	never	used
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> { … }
class FutureController<T> {
val future = CompletableFuture<T>()
operator fun handleResult(value: T) {
future.complete(value)
}
operator fun handleException(exception: Throwable) {
future.completeExceptionally(exception)
}
}
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> { … }
class FutureController<T> {
val future = CompletableFuture<T>()
operator fun handleResult(value: T) {
future.complete(value)
}
operator fun handleException(exception: Throwable) {
future.completeExceptionally(exception)
}
}
Looks	like	Continuation<T>
Coroutine	builders	(prototype)
fun <T> async(
coroutine c: FutureController<T>.() -> Continuation<Unit>
): CompletableFuture<T> { … }
class FutureController<T> {
val future = CompletableFuture<T>()
operator fun handleResult(value: T) {
future.complete(value)
}
operator fun handleException(exception: Throwable) {
future.completeExceptionally(exception)
}
}
Something	that	takes	Continuation<T>
Coroutine	builders:	evolved
Coroutine	builders
fun <T> async(
c: suspend () -> T
): CompletableFuture<T> {
val controller = FutureController<T>()
c.startCoroutine(completion = controller)
return controller.future
}
Coroutine	builders
fun <T> async(
c: suspend () -> T
): CompletableFuture<T> {
val controller = FutureController<T>()
c.startCoroutine(completion = controller)
return controller.future
}
natural	signature
No	special	coroutine keyword
Coroutine	builders
fun <T> async(
c: suspend () -> T
): CompletableFuture<T> {
val controller = FutureController<T>()
c.startCoroutine(completion = controller)
return controller.future
}
Provided	by	standard	library
Coroutine	builders
fun <T> async(
c: suspend () -> T
): CompletableFuture<T> { … }
class FutureController<T> : Continuation<T> {
val future = CompletableFuture<T>()
override fun resume(value: T) {
future.complete(value)
}
override fun resumeWithException(exception: Throwable) {
future.completeExceptionally(exception)
}
}
Coroutine	builders
fun <T> async(
c: suspend () -> T
): CompletableFuture<T> { … }
class FutureController<T> : Continuation<T> {
val future = CompletableFuture<T>()
override fun resume(value: T) {
future.complete(value)
}
override fun resumeWithException(exception: Throwable) {
future.completeExceptionally(exception)
}
}
Serves	as	completion
continuation	for	coroutine
Bonus	features
Free	as	in	cheese
Arbitrary	suspending	calls
suspend fun <T> suspending(block: suspend () -> T): T =
suspendCoroutine { continuation ->
block.startCoroutine(completion = continuation)
}
Arbitrary	suspending	calls
suspend fun <T> suspending(block: suspend () -> T): T =
suspendCoroutine { continuation ->
block.startCoroutine(completion = continuation)
}
Arbitrary	suspending	calls
suspend fun <T> suspending(block: suspend () -> T): T =
suspendCoroutine { continuation ->
block.startCoroutine(completion = continuation)
}
Arbitrary	suspending	calls
suspend fun <T> suspending(block: suspend () -> T): T =
suspendCoroutine { continuation ->
block.startCoroutine(completion = continuation)
}
fun moreWork() = async {
println("Work started")
val str = work().await()
println("Work completed: $str")
}
Returns	CompletableFuture
Arbitrary	suspending	calls
suspend fun <T> suspending(block: suspend () -> T): T =
suspendCoroutine { continuation ->
block.startCoroutine(completion = continuation)
}
suspend fun moreWork(): T = suspending {
println("Work started")
val str = work().await()
println("Work completed: $str")
}
Arbitrary	suspending	calls
suspend fun <T> suspending(block: suspend () -> T): T =
suspendCoroutine { continuation ->
block.startCoroutine(completion = continuation)
}
suspend fun moreWork(): T = suspending {
println("Work started")
val str = work().await()
println("Work completed: $str")
}
Tail	suspend	invocation
Non-tail	(arbitrary)	suspend	invocation
Arbitrary	suspending	calls
suspend fun moreWork() {
println("Work started")
val str = work().await()
println("Work completed: $str")
}
Non-tail	(arbitrary)	suspend	invocation
Stackless vs	Stackful coroutines
The	crucial	distinction
Stackless vs	Stackful coroutines
Stackless Stackful
Restrictions Use	in	special ctx Use	anywhere
Implemented in C#,	Scala,	Kotlin, … Quasar, Javaflow,	…
Stackless vs	Stackful coroutines
Stackless Stackful
Restrictions Use	in	special ctx Use	anywhere
Implemented in C#,	Scala,	Kotlin, … Quasar, Javaflow,	…
Stackless vs	Stackful coroutines
Stackless Stackful
Restrictions Use	in	special ctx Use	anywhere
Implemented in C#,	Scala,	Kotlin, … Quasar, Javaflow,	…
Can suspend	in? suspend
functions
throws SuspendExecution /	
@Suspendable functions
Stackless vs	Stackful coroutines
Stackless Stackful
Restrictions Use	in	special ctx Use	anywhere
Implemented in C#,	Scala, … Kotlin,	Quasar, Javaflow,	…
Stackless vs	Stackful coroutines
Stackless Stackful
Restrictions Use	in	special ctx Use	anywhere
Implemented in C#,	Scala, Kotlin,	
Quasar, JavaFlow,	…
LISP,	Go,	…
Stackless vs	Stackful coroutines
Stackless Stackful
Restrictions Use	in	special ctx Use	anywhere
Implemented in C#,	Scala, … Kotlin,	Quasar, Javaflow,	…
False	
dichotomy
Async	vs	Suspending	functions
The	actual	difference
fun work() = async { … }
suspend fun work() { … }
fun work(): CompletableFuture<String> = async { … }
suspend fun work(): String { … }
In	Kotlin	you	have a	choice
fun workAsync(): CompletableFuture<String> = async { … }
suspend fun work(): String { … }
workAsync() VALID –>	produces	CompletableFuture<String>
workAsync().await() VALID –>	produces	String
concurrent	&	async	behavior
sequential	behavior
The	most	needed one,	yet	the	most	syntactically	
clumsy,	esp.	for	suspend-heavy	(CSP)	code	style	
The	problem	with	async
Kotlin	suspending	functions	
imitate	sequential behavior	
by	default	
Concurrency	is	hard
Concurrency	has	to	be	explicit
Composability
Making	those	legos click
Builders
fun <T> async(
c: suspend () -> T
): CompletableFuture<T> { … }
Builders
fun <T> async(
c: suspend () -> T
): ListenableFuture<T> { … }
Builders
fun <T> async(
c: suspend () -> T
): MyOwnFuture<T> { … }
Suspending	functions
fun <T> async(
c: suspend () -> T
): MyOwnFuture<T> { … }
suspend fun <T> CompletableFuture<T>.await(): T { … }
Suspending	functions
fun <T> async(
c: suspend () -> T
): MyOwnFuture<T> { … }
suspend fun <T> ListenableFuture<T>.await(): T { … }
Suspending	functions
fun <T> async(
c: suspend () -> T
): MyOwnFuture<T> { … }
suspend fun <T> MyOwnFuture<T>.await(): T { … }
Suspending	functions
fun <T> async(
c: suspend () -> T
): MyOwnFuture<T> { … }
suspend fun <T> MyOwnFuture<T>.await(): T { … }
fun moreWorkAsync() = async {
println("Work started")
val str = workAsync().await()
println("Work completed: $str")
}
All	combinations	need	to	compose
Composability:	evolved
• Kotlin	suspending	functions	are	composable by	default	
• Asynchronous use-case
• Define	asynchronous	suspending	functions	anywhere
• Use	them	inside	any	asynchronous	coroutine	builder
• Or	inside	other	suspending	functions
• generate/yield coroutines	are	synchronous
• Restricted	via	a	special	@RestrictsSuspension annotation
• Opt-in	to	define	synchronous	coroutines
Coroutine	context
The	last	piece	of	composability	puzzle
asyncUI (prototype)
asyncUI {
val image = await(loadImage(url))
myUI.updateImage(image)
}
Supposed	to	work	in	UI	thread
asyncUI (prototype)
asyncUI {
val image = await(loadImage(url))
myUI.updateImage(image)
}
A	special	coroutine	builder
asyncUI (prototype)
asyncUI {
val image = await(loadImage(url))
myUI.updateImage(image)
}
A	special	suspending	function in	its	scope
Composability	problem	
again!
asyncUI:	evolved
async(UI) {
val image = loadImageAsync(url).await()
myUI.updateImage(image)
}
asyncUI:	evolved
async(UI) {
val image = loadImageAsync(url).await()
myUI.updateImage(image)
}
Explicit	context	convention for	all	builders
Can	intercept continuation	to	
resume	in	the	appropriate	thread
The	actual	Continuation	interface
async(UI) {
val image = loadImageAsync(url).await()
myUI.updateImage(image)
}
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Is	used	to	transparently	lookup	an	
interceptor	for	resumes
The	actual	Continuation	interface
async(UI) {
val image = loadImageAsync(url).await()
myUI.updateImage(image)
}
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Does	not	have	to	be	aware	– receives	
intercepted	continuation	to	work	with
Thread-safety
A	million-dollar	quest	for	correctly-synchronized	(data-race	free)	code
A	need	for	happens-before	relation
fun moreWork() = async {
val list = ArrayList<String>()
val str = work().await()
list.add(str)
}
A	need	for	happens-before	relation
fun moreWork() = async {
val list = ArrayList<String>()
val str = work().await()
list.add(str)
}
One	thread
A	need	for	happens-before	relation
fun moreWork() = async {
val list = ArrayList<String>()
val str = work().await()
list.add(str)
}
One	thread
Suspends	/	resumes
A	need	for	happens-before	relation
fun moreWork() = async {
val list = ArrayList<String>()
val str = work().await()
list.add(str)
}
One	thread
Suspends	/	resumes
Another	thread
A	need	for	happens-before	relation
fun moreWork() = async {
val list = ArrayList<String>()
val str = work().await()
list.add(str)
}
One	thread
Suspends	/	resumes
Another	thread
Is	there	a	data	race?
Do	we	need	volatile	when	spilling	
locals	to	a	state	machine?
A	need	for	happens-before	relation
fun moreWork() = async {
val list = ArrayList<String>()
val str = work().await()
list.add(str)
}
There	is	no	data	race	here!	
await establishes	happens-before	relation
happens-before
Challenges
If	it	only	was	all	that	simple…
Thread	confinement	vs	coroutines
fun moreWork() = async {
synchronized(monitor) {
val str = work().await()
}
}
Thread	confinement	vs	coroutines
fun moreWork() = async {
synchronized(monitor) {
val str = work().await()
}
}
MONITORENTER in	one	thread
Suspends	/	resumes
MONITOREXIT in	another	thread
IllegalMonitorStateException
Thread	confinement	vs	coroutines
• Monitors
• Locks	(j.u.c.l.ReentrantLock)
• Thread-locals
• …
• Thread.currentThread()
A	CoroutineContext is	a	map	of	
coroutine-local	elements	as	replacement
Stack	traces	in	exceptions
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
stack
moreWork
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
stack
moreWork
work
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
stack
moreWork
work
await
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
stack
moreWork
work
Work$StateMachine :
Continuation
----------
fun resume(v)
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
stack
Work$StateMachine.resume
work
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
JVM	stack
Work$StateMachine.resume
work
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
JVM	stack
Work$StateMachine.resume
work
Coroutine	stack
moreWork
work
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
JVM	stack
Work$StateMachine.resume
work
Coroutine	stack
moreWork
work
Gets	thrown
Stack	traces	in	exceptions
suspend fun moreWork() {
work()
}
suspend fun work() {
someAsyncOp().await()
throw Exception()
}
JVM	stack
Work$StateMachine.resume
work
Coroutine	stack
moreWork
work
Gets	thrown User	wants
Library	evolution
Going	beyond	the	language	&	stdlib
Library	evolution:	already	there
• Communication	&	synchronization	primitives
• Job:	A	completable &	cancellable	entity	to	represent	a	coroutine
• Deferred:	A	future	with	suspend fun	await (and	no thread-blocking	methods)
• Mutex:	with	suspend fun	lock
• Channel:	SendChannel &	ReceiveChannel
• RendezvousChannel – synchronous	rendezvous
• ArrayChannel – fixed	size	buffer
• LinkedListChannel – unlimited	buffer
• ConflatedChannel – only	the	most	recent	sent	element	is	kept
• BroadcastChannel:	multiple	subscribes,	all	receive
Library	evolution:	already	there
• Coroutine	builders
• launch (fire	&	forget,	returns	a	Job)
• async (returns	Deferred)
• future	(integration	with	CompletableFuture &	ListenableFuture)
• runBlocking (to	explicitly	delimit	code	that	blocks	a	thread)
• actor	/ produce	(consume	&	produce	messages	over	channels)
• publish (integration	with	reactive	streams,	returns	Publisher)
• rxCompletable,	rxSingle,	rxObservable,	rxFlowable (RxJava 1/2)
Library	evolution:	already	there
• Top-level	functions	
• select expression	to	await	multiple	events	for	full	CSP-style	programming
• delay	for	time-based	logic	in	coroutines	
• Extensions
• await for	all	kinds	of	futures	(JDK,	Guava,	RxJava)
• aRead,	aWrite,	etc for	AsynchronousXxxChannel in	NIO
• Cancellation	&	job	(coroutine/actor)	hierarchies
• withTimeout for	a	composable way	for	any	suspend	function	run	w/timeout
Library	evolution:	WIP
• Serialization	/	migration	of	coroutines
• Migrating	libraries	to	Kotlin/JS	&	Kotlin/Native	(lang support	– done)
• Full	scope	of	pipelining	operators	on	channels	(filter,	map,	etc)
• Optimizations	for	single-producer	and/or	single-consumer	cases
• Allow	3rd party	primitives	to	participate	in	select (alternatives)
• ByteChannel for	suspendable IO	(http	client/server,	websocket,	etc)
• See	also	ktor.io
A	closing	note	on	terminology
• We	don’t	use	the	term	fiber/strand/green	threads/…
• The	term	coroutine works	just	as	well
• ”Fibers	describe	essentially	the	same	concept	as	coroutines”	©	Wikipedia
Kotlin	Coroutines	are	very light-weight	threads
Wrap	up
Let’s	call	it	a	day
Experimental	status	of	coroutines
• This	design	is	new and	unlike	mainstream
• For	some	very	good	reasons
• We	want	community	to	try	it	for	real
• So	we	released	it	as	an	experimental feature
• We	guarantee	backwards	compatibility
• Old	code	compiled	with	coroutines	continues	to	work
• We	reserve	the	right	to	break	forward	compatibility
• We	may	add	things	so	new	code	may	not	run	w/old	RT
• Design	will	be	finalized	at	a	later	point
• Old	code	will	continue	to	work	via	support	library
• Migration	aids	to	the	final	design	will	be	provided
opt-in	flag
Thank	you
Any	questions?
Slides	are	available	at	www.slideshare.net/elizarov
email	elizarov at	gmail
relizarov

Weitere ähnliche Inhalte

Was ist angesagt?

Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
Adieu
 

Was ist angesagt? (20)

Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutines
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
 
Kotlin
KotlinKotlin
Kotlin
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Jetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no AndroidJetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no Android
 
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
 
Kotlin
KotlinKotlin
Kotlin
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
In-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsIn-depth analysis of Kotlin Flows
In-depth analysis of Kotlin Flows
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
 
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
 
[JS EXPERIENCE 2018] Javascript Event Loop além do setInterval - Derek Stavis
[JS EXPERIENCE 2018] Javascript Event Loop além do setInterval - Derek Stavis[JS EXPERIENCE 2018] Javascript Event Loop além do setInterval - Derek Stavis
[JS EXPERIENCE 2018] Javascript Event Loop além do setInterval - Derek Stavis
 
Kotlin InDepth Tutorial for beginners 2022
Kotlin InDepth Tutorial for beginners 2022Kotlin InDepth Tutorial for beginners 2022
Kotlin InDepth Tutorial for beginners 2022
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
Kotlin coroutines
Kotlin coroutinesKotlin coroutines
Kotlin coroutines
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
 

Ähnlich wie Kotlin Coroutines Reloaded

yield and return (poor English ver)
yield and return (poor English ver)yield and return (poor English ver)
yield and return (poor English ver)
bleis tift
 

Ähnlich wie Kotlin Coroutines Reloaded (20)

JVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in KotlinJVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in Kotlin
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenes
 
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel ZikmundNDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using Scala
 
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
 
Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx
 
Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - Coroutine
 
Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programování
 
Advanced patterns in asynchronous programming
Advanced patterns in asynchronous programmingAdvanced patterns in asynchronous programming
Advanced patterns in asynchronous programming
 
yield and return (poor English ver)
yield and return (poor English ver)yield and return (poor English ver)
yield and return (poor English ver)
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 
Property based testing
Property based testingProperty based testing
Property based testing
 
Namespaces
NamespacesNamespaces
Namespaces
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Python Coroutines, Present and Future
Python Coroutines, Present and FuturePython Coroutines, Present and Future
Python Coroutines, Present and Future
 
Kotlin boost yourproductivity
Kotlin boost yourproductivityKotlin boost yourproductivity
Kotlin boost yourproductivity
 

Mehr von Roman Elizarov

Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и Практика
Roman Elizarov
 
Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)
Roman Elizarov
 
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Roman Elizarov
 
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
Roman Elizarov
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and Fallacies
Roman Elizarov
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
Roman Elizarov
 
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
Roman Elizarov
 
The theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerThe theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmer
Roman Elizarov
 

Mehr von Roman Elizarov (19)

Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017
 
Scale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOneScale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOne
 
Lock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesLock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin Coroutines
 
Non blocking programming and waiting
Non blocking programming and waitingNon blocking programming and waiting
Non blocking programming and waiting
 
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
 
Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и Практика
 
Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Wait for your fortune without Blocking!
Wait for your fortune without Blocking!
 
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
 
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?
 
Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)
 
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
 
DIY Java Profiling
DIY Java ProfilingDIY Java Profiling
DIY Java Profiling
 
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and Fallacies
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
 
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
 
The theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerThe theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmer
 
Пишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхПишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данных
 

Kürzlich hochgeladen

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Kürzlich hochgeladen (20)

Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 

Kotlin Coroutines Reloaded