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

Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKirill Rozov
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlinintelliyole
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutinesBipin Vayalu
 
Improving app performance with Kotlin Coroutines
Improving app performance with Kotlin CoroutinesImproving app performance with Kotlin Coroutines
Improving app performance with Kotlin CoroutinesHassan Abid
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in GolangOliver N
 
Go Concurrency
Go ConcurrencyGo Concurrency
Go Concurrencyjgrahamc
 
Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8RichardWarburton
 
Structured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin CoroutinesStructured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin CoroutinesVadims Savjolovs
 
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 CoroutinesLauren Yew
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKai Koenig
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseChristian Melchior
 
Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!Nico Krijnen
 
gRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquaregRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquareApigee | Google Cloud
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event LoopDesignveloper
 
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
 

What's hot (20)

Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutines
 
Improving app performance with Kotlin Coroutines
Improving app performance with Kotlin CoroutinesImproving app performance with Kotlin Coroutines
Improving app performance with Kotlin Coroutines
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in Golang
 
Go Concurrency
Go ConcurrencyGo Concurrency
Go Concurrency
 
Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8
 
Completable future
Completable futureCompletable future
Completable future
 
Structured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin CoroutinesStructured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin Coroutines
 
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 Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in Practise
 
Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
gRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquaregRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at Square
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
 
Kotlin
KotlinKotlin
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...
 

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)

4 sesame
4 sesame4 sesame
4 sesame
 
SWT Lecture Session 4 - Sesame
SWT Lecture Session 4 - SesameSWT Lecture Session 4 - Sesame
SWT Lecture Session 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

WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 

Recently uploaded (20)

WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

Kotlin Coroutines in Practice @ KotlinConf 2018