SlideShare a Scribd company logo
1 of 128
Download to read offline
elizarov@
Roman Elizarov
Kotlin Coroutines in
Practice
@relizarov
Coroutines recap
Coroutines are like
light-weight threads
suspend fun main() {
val jobs = List(100_000) {
GlobalScope.launch {
delay(5000)
print(".")
}
}
jobs.forEach { it.join() }
}
Coroutines are like
light-weight threads
suspend fun main() {
val jobs = List(100_000) {
GlobalScope.launch {
delay(5000)
print(".")
}
}
jobs.forEach { it.join() }
}
Coroutines are like
light-weight threads
suspend fun main() {
val jobs = List(100_000) {
GlobalScope.launch {
delay(5000)
print(".")
}
}
jobs.forEach { it.join() }
}
Coroutines are like
light-weight threads
Quantity
Quantity → Quality
A practical challenge
suspend fun downloadContent(location: Location): Content
fun processReferences(refs: List<Reference>)
References
References
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
…
}
}
References Locations
resolve
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
…
}
}
References Locations Contents
resolve download
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
val content = downloadContent(location)
processContent(ref, content)
}
}
References Locations Contents
resolve download
suspend fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
val content = downloadContent(location)
processContent(ref, content)
}
}
References Locations Contents
resolve download
suspend fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
val content = downloadContent(location)
processContent(ref, content)
}
}
Sequential
References Locations Contents
resolve download
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
val content = downloadContent(location)
processContent(ref, content)
}
}
Parallel
References Locations Contents
resolve download
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
GlobalScope.launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Parallel
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
GlobalScope.launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Coroutines are cheap! What could go wrong?
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
GlobalScope.launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
ref1 location1 Launch download
ref2 location2 Launch download
ref3
Crash!
Crash!
ref1 location1 Launch download
ref2 location2 Launch download
ref3
Crash!
Crash! Leak!
fun processReferences(refs: List<Reference>) {
for (ref in refs) {
val location = ref.resolveLocation()
GlobalScope.launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Structured
concurrency
fun processReferences(refs: List<Reference>)
suspend fun processReferences(refs: List<Reference>)
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
…
}
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
GlobalScope.launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Child
Crash?
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Crash?
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Crash?
cancels
Crash?
cancels
Waits for completion
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
suspend fun processReferences(refs: List<Reference>) =
coroutineScope {
for (ref in refs) {
val location = ref.resolveLocation()
launch {
val content = downloadContent(location)
processContent(ref, content)
}
}
}
Never leaks jobs
The state
References Contents
Download process
Reference 1
Content
Reference 2
Location
Download process
State
class Downloader {
}
class Downloader {
private val requested = mutableSetOf<Location>()
}
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
…
}
}
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
}
}
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
Concurrent
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
Concurrent
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
Shared mutable state
class Downloader {
private val requested = mutableSetOf<Location>()
fun downloadReference(ref: Reference) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
Shared mutable state
Needs Synchronization
Shared + Mutable =
Shared
Mutable State
Share by
Communicating
Synchronization
Primitives
Communication
Primitives
classes coroutines
launch {
val requested = mutableSetOf<Location>()
…
}
Does not share mutable state
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
Channel
References
Downloader
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
…
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
…
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
…
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
…
}
Convention
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
// schedule download
}
// ... wait for result ...
processContent(ref, content)
}
}
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
launch { … }
}
// ... wait for result ...
processContent(ref, content)
}
}
Coroutines are cheap! What could go wrong?
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
launch { … }
}
// ... wait for result ...
processContent(ref, content)
}
}
Child
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
launch { … }
}
// ... wait for result ...
processContent(ref, content)
}
}
Coroutines are cheap! But the work they do…
Limiting
concurrency
Worker 1
Worker 2
Worker 3
Worker N
Worker pool
…
References
Downloader
references locations
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
locations: SendChannel<Location>
)
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
locations: SendChannel<Location>
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
locations.send(location)
}
}
}
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
)
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
)
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
) =
launch {
for (loc in locations) {
val content = downloadContent(loc)
processContent(ref, content)
}
}
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
) =
launch {
for (loc in locations) {
val content = downloadContent(loc)
processContent(ref, content)
}
}
Fan-out
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
) =
launch {
for (loc in locations) {
val content = downloadContent(location)
processContent(ref, content)
}
}
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
) =
launch {
for (loc in locations) {
val content = downloadContent(loc)
processContent(ref, content)
}
}
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>
) =
launch {
for (loc in locations) {
val content = downloadContent(loc)
processContent(ref, content)
}
}
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
Refs ↔ Locs
location &
content
data class LocContent(val loc: Location, val content: Content)
data class LocContent(val loc: Location, val content: Content)
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>,
contents: SendChannel<LocContent>
)
data class LocContent(val loc: Location, val content: Content)
fun CoroutineScope.worker(
locations: ReceiveChannel<Location>,
contents: SendChannel<LocContent>
) =
launch {
for (loc in locations) {
val content = downloadContent(loc)
contents.send(LocContent(loc, content))
}
}
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
locations
contents
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
locations: SendChannel<Location>,
contents: ReceiveChannel<LocContent>
)
fun CoroutineScope.downloader(
references: ReceiveChannel<Reference>,
locations: SendChannel<Location>,
contents: ReceiveChannel<LocContent>
) =
launch {
val requested = mutableSetOf<Location>()
for (ref in references) {
val location = ref.resolveLocation()
if (requested.add(location)) {
locations.send(location)
}
}
}
Hmm….
Select
select {
references.onReceive { ref ->
…
}
contents.onReceive { (loc, content) ->
…
}
}
select {
references.onReceive { ref ->
…
}
contents.onReceive { (loc, content) ->
…
}
}
select<Unit> {
references.onReceive { ref ->
…
}
contents.onReceive { (loc, content) ->
…
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
…
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref -> … }
contents.onReceive { (loc, content) -> … }
}
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref -> … }
contents.onReceive { (loc, content) -> … }
}
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref ->
val loc = ref.resolveLocation()
…
}
contents.onReceive { (loc, content) -> … }
}
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref ->
val loc = ref.resolveLocation()
val refs = requested[loc]
…
}
contents.onReceive { (loc, content) -> … }
}
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref ->
val loc = ref.resolveLocation()
val refs = requested[loc]
if (refs == null) {
requested[loc] = mutableListOf(ref)
locations.send(loc)
}
}
contents.onReceive { (loc, content) -> … }
}
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref ->
val loc = ref.resolveLocation()
val refs = requested[loc]
if (refs == null) {
requested[loc] = mutableListOf(ref)
locations.send(loc)
} else {
refs.add(ref)
}
}
contents.onReceive { (loc, content) -> … }
}
}
}
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref ->
val loc = ref.resolveLocation()
val refs = requested[loc]
if (refs == null) {
requested[loc] = mutableListOf(ref)
locations.send(loc)
} else {
refs.add(ref)
}
}
contents.onReceive { (loc, content) -> … }
}
}
}
No concurrency
No synchronization
launch {
val requested = mutableMapOf<Location, MutableList<Reference>>()
while (true) {
select<Unit> {
references.onReceive { ref -> … }
contents.onReceive { (loc, content) ->
val refs = requested.remove(loc)!!
for (ref in refs) {
processContent(ref, content)
}
}
}
}
}
Putting it all
together
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
locations
contents
references
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
locations
contents
references
fun CoroutineScope.processReferences(
references: ReceiveChannel<Reference>
)
fun CoroutineScope.processReferences(
references: ReceiveChannel<Reference>
)
fun CoroutineScope.processReferences(
references: ReceiveChannel<Reference>
) {
val locations = Channel<Location>()
val contents = Channel<LocContent>()
repeat(N_WORKERS) { worker(locations, contents) }
downloader(references, locations, contents)
}
fun CoroutineScope.processReferences(
references: ReceiveChannel<Reference>
) {
val locations = Channel<Location>()
val contents = Channel<LocContent>()
repeat(N_WORKERS) { worker(locations, contents) }
downloader(references, locations, contents)
}
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
locations
contents
references
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
locations
contents
references
processReferences
Worker 1
Worker 2
Worker 3
Worker N
…
References
Downloader
locations
contents
references
processReferences
Patterns
everywhere Worker pool
Actor
fun CoroutineScope.processReferences(…)
Root
CoroutineScope
class SomethingWithLifecycle {
}
class SomethingWithLifecycle : CoroutineScope {
}
class SomethingWithLifecycle : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = …
}
class SomethingWithLifecycle : CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = …
}
class SomethingWithLifecycle : CoroutineScope {
private val job = Job()
fun dispose() { … }
override val coroutineContext: CoroutineContext
get() = …
}
class SomethingWithLifecycle : CoroutineScope {
private val job = Job()
fun close() { … }
override val coroutineContext: CoroutineContext
get() = …
}
class SomethingWithLifecycle : CoroutineScope {
private val job = Job()
fun close() {
job.cancel()
}
override val coroutineContext: CoroutineContext
get() = …
}
class SomethingWithLifecycle : CoroutineScope {
private val job = Job()
fun close() {
job.cancel()
}
override val coroutineContext: CoroutineContext
get() = job
}
class SomethingWithLifecycle : CoroutineScope {
private val job = Job()
fun close() {
job.cancel()
}
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
}
class SomethingWithLifecycle : CoroutineScope {
…
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
fun doSomething() {
}
}
class SomethingWithLifecycle : CoroutineScope {
…
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
fun doSomething() {
launch { … }
}
}
class SomethingWithLifecycle : CoroutineScope {
…
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
fun doSomething() {
processReferences(references)
}
}
Never leak any coroutines
suspend vs scope
suspend fun downloadContent(location: Location): Content
suspend fun downloadContent(location: Location): Content
Does something long &
waits for it to complete without blocking
suspend fun downloadContent(location: Location): Content
fun CoroutineScope.processReferences(…)
suspend fun downloadContent(location: Location): Content
fun CoroutineScope.processReferences(…)
Launches new coroutines &
quickly returns, does not wait for them
Takeaway
Coroutines are like
light-weight threads
Coroutines are NOT like
threads
Coroutines are NOT like
threads
Rethink the way you
structure your code
Thank you
Any questions?
elizarov@
Roman Elizarov
@relizarov

More Related Content

What's hot

Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutinesNAVER Engineering
 
Coroutines in Kotlin
Coroutines in KotlinCoroutines in Kotlin
Coroutines in KotlinAlexey Soshin
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOJorge Vásquez
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesAnh Vu
 
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 applicationSeven Peaks Speaks
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidNelson Glauber Leal
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftCommit University
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsScott Wlaschin
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutinesBipin Vayalu
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack TutorialSimplilearn
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modelingMario Fusco
 
Jetpack Compose - A Lightning Tour
Jetpack Compose - A Lightning TourJetpack Compose - A Lightning Tour
Jetpack Compose - A Lightning TourMatthew Clarke
 
In-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsIn-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsGlobalLogic Ukraine
 
Javascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big PictureJavascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big PictureManish Jangir
 
FS_module_functions.pptx
FS_module_functions.pptxFS_module_functions.pptx
FS_module_functions.pptxBareen Shaikh
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseChristian Melchior
 

What's hot (20)

Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
 
Coroutines in Kotlin
Coroutines in KotlinCoroutines in Kotlin
Coroutines in Kotlin
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenes
 
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
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on Android
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and Swift
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutines
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack Tutorial
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 
Async Programming in C# 5
Async Programming in C# 5Async Programming in C# 5
Async Programming in C# 5
 
Jetpack Compose - A Lightning Tour
Jetpack Compose - A Lightning TourJetpack Compose - A Lightning Tour
Jetpack Compose - A Lightning Tour
 
In-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsIn-depth analysis of Kotlin Flows
In-depth analysis of Kotlin Flows
 
Javascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big PictureJavascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big Picture
 
FS_module_functions.pptx
FS_module_functions.pptxFS_module_functions.pptx
FS_module_functions.pptx
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in Practise
 

Similar to Kotlin Coroutines in Practice @ KotlinConf 2018

Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
Designing a JavaFX Mobile application
Designing a JavaFX Mobile applicationDesigning a JavaFX Mobile application
Designing a JavaFX Mobile applicationFabrizio Giudici
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applicationsSteve Smith
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page ApplicationsSteve Smith
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackNelson Glauber Leal
 
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...DynamicInfraDays
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresiMasters
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Astrails
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin CoroutinesEamonn Boyle
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0SO
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii명철 강
 
Introduction to Spark with Scala
Introduction to Spark with ScalaIntroduction to Spark with Scala
Introduction to Spark with ScalaHimanshu Gupta
 
Serverless Ballerina
Serverless BallerinaServerless Ballerina
Serverless BallerinaBallerina
 

Similar to Kotlin Coroutines in Practice @ KotlinConf 2018 (20)

SWT Lecture Session 4 - Sesame
SWT Lecture Session 4 - SesameSWT Lecture Session 4 - Sesame
SWT Lecture Session 4 - Sesame
 
4 sesame
4 sesame4 sesame
4 sesame
 
Apache Beam de A à Z
 Apache Beam de A à Z Apache Beam de A à Z
Apache Beam de A à Z
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Play á la Rails
Play á la RailsPlay á la Rails
Play á la Rails
 
Why react matters
Why react mattersWhy react matters
Why react matters
 
Designing a JavaFX Mobile application
Designing a JavaFX Mobile applicationDesigning a JavaFX Mobile application
Designing a JavaFX Mobile application
 
Kitura Todolist tutorial
Kitura Todolist tutorialKitura Todolist tutorial
Kitura Todolist tutorial
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applications
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page Applications
 
Unfiltered Unveiled
Unfiltered UnveiledUnfiltered Unveiled
Unfiltered Unveiled
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
 
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
 
Introduction to Spark with Scala
Introduction to Spark with ScalaIntroduction to Spark with Scala
Introduction to Spark with Scala
 
Serverless Ballerina
Serverless BallerinaServerless Ballerina
Serverless Ballerina
 

More from Roman Elizarov

Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Roman Elizarov
 
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 @ JavaOneRoman Elizarov
 
Lock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesLock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesRoman Elizarov
 
Non blocking programming and waiting
Non blocking programming and waitingNon blocking programming and waiting
Non blocking programming and waitingRoman Elizarov
 
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 ReviewRoman Elizarov
 
Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаRoman Elizarov
 
Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Roman Elizarov
 
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 ReviewRoman Elizarov
 
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 ReviewRoman Elizarov
 
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?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 ReviewRoman Elizarov
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and FallaciesRoman 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 javaRoman 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 ReviewRoman 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 programmerRoman Elizarov
 
Пишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхПишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхRoman Elizarov
 

More from 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
 
Пишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхПишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данных
 

Recently uploaded

How to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxHow to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxKaustubhBhavsar6
 
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptxEmil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptxNeo4j
 
2024.03.12 Cost drivers of cultivated meat production.pdf
2024.03.12 Cost drivers of cultivated meat production.pdf2024.03.12 Cost drivers of cultivated meat production.pdf
2024.03.12 Cost drivers of cultivated meat production.pdfThe Good Food Institute
 
Planetek Italia Srl - Corporate Profile Brochure
Planetek Italia Srl - Corporate Profile BrochurePlanetek Italia Srl - Corporate Profile Brochure
Planetek Italia Srl - Corporate Profile BrochurePlanetek Italia Srl
 
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - TechWebinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - TechProduct School
 
From the origin to the future of Open Source model and business
From the origin to the future of  Open Source model and businessFrom the origin to the future of  Open Source model and business
From the origin to the future of Open Source model and businessFrancesco Corti
 
TrustArc Webinar - How to Live in a Post Third-Party Cookie World
TrustArc Webinar - How to Live in a Post Third-Party Cookie WorldTrustArc Webinar - How to Live in a Post Third-Party Cookie World
TrustArc Webinar - How to Live in a Post Third-Party Cookie WorldTrustArc
 
Novo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNovo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNeo4j
 
Introduction to RAG (Retrieval Augmented Generation) and its application
Introduction to RAG (Retrieval Augmented Generation) and its applicationIntroduction to RAG (Retrieval Augmented Generation) and its application
Introduction to RAG (Retrieval Augmented Generation) and its applicationKnoldus Inc.
 
UiPath Studio Web workshop series - Day 1
UiPath Studio Web workshop series  - Day 1UiPath Studio Web workshop series  - Day 1
UiPath Studio Web workshop series - Day 1DianaGray10
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfCheryl Hung
 
Where developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is goingWhere developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is goingFrancesco Corti
 
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Alkin Tezuysal
 
3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud Data3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud DataEric D. Schabell
 
20140402 - Smart house demo kit
20140402 - Smart house demo kit20140402 - Smart house demo kit
20140402 - Smart house demo kitJamie (Taka) Wang
 
Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Muhammad Tiham Siddiqui
 
UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3DianaGray10
 
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedInOutage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedInThousandEyes
 
Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.IPLOOK Networks
 
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTSIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTxtailishbaloch
 

Recently uploaded (20)

How to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxHow to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptx
 
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptxEmil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
 
2024.03.12 Cost drivers of cultivated meat production.pdf
2024.03.12 Cost drivers of cultivated meat production.pdf2024.03.12 Cost drivers of cultivated meat production.pdf
2024.03.12 Cost drivers of cultivated meat production.pdf
 
Planetek Italia Srl - Corporate Profile Brochure
Planetek Italia Srl - Corporate Profile BrochurePlanetek Italia Srl - Corporate Profile Brochure
Planetek Italia Srl - Corporate Profile Brochure
 
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - TechWebinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
 
From the origin to the future of Open Source model and business
From the origin to the future of  Open Source model and businessFrom the origin to the future of  Open Source model and business
From the origin to the future of Open Source model and business
 
TrustArc Webinar - How to Live in a Post Third-Party Cookie World
TrustArc Webinar - How to Live in a Post Third-Party Cookie WorldTrustArc Webinar - How to Live in a Post Third-Party Cookie World
TrustArc Webinar - How to Live in a Post Third-Party Cookie World
 
Novo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNovo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4j
 
Introduction to RAG (Retrieval Augmented Generation) and its application
Introduction to RAG (Retrieval Augmented Generation) and its applicationIntroduction to RAG (Retrieval Augmented Generation) and its application
Introduction to RAG (Retrieval Augmented Generation) and its application
 
UiPath Studio Web workshop series - Day 1
UiPath Studio Web workshop series  - Day 1UiPath Studio Web workshop series  - Day 1
UiPath Studio Web workshop series - Day 1
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Where developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is goingWhere developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is going
 
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
 
3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud Data3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud Data
 
20140402 - Smart house demo kit
20140402 - Smart house demo kit20140402 - Smart house demo kit
20140402 - Smart house demo kit
 
Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)
 
UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3
 
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedInOutage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
 
Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.
 
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTSIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
 

Kotlin Coroutines in Practice @ KotlinConf 2018