Skip to content

Instantly share code, notes, and snippets.

@pkulak
Last active April 7, 2019 22:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkulak/7601200d51e148685b0f0337cd6c299b to your computer and use it in GitHub Desktop.
Save pkulak/7601200d51e148685b0f0337cd6c299b to your computer and use it in GitHub Desktop.
Map an iterable asynchronously using limited concurrency.
/**
* A very simple, non-blocking semaphore.
*/
class Semaphore(capacity: Int) {
private val channel = Channel<Boolean>(capacity)
suspend fun acquire() {
channel.send(true)
}
suspend fun release() {
channel.receive()
}
}
/**
* Maps the iterable asynchronously using at most the given given concurrency.
*/
suspend fun <T, R> Iterable<T>.mapAsync(concurrency: Int, transform: suspend (T) -> R): List<R> = coroutineScope {
val semaphore = Semaphore(concurrency)
map {
semaphore.acquire()
async { transform(it).also { semaphore.release() } }
}
.map { it.await() }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment