{"id":16923773,"url":"https://github.com/bugaevc/coroutines-lite","last_synced_at":"2025-03-21T00:29:54.982Z","repository":{"id":71726535,"uuid":"407145140","full_name":"bugaevc/coroutines-lite","owner":"bugaevc","description":null,"archived":false,"fork":false,"pushed_at":"2021-11-04T20:46:47.000Z","size":385,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-25T21:11:56.727Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bugaevc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-16T11:51:36.000Z","updated_at":"2025-01-06T18:57:18.000Z","dependencies_parsed_at":"2023-04-05T15:48:26.929Z","dependency_job_id":null,"html_url":"https://github.com/bugaevc/coroutines-lite","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugaevc%2Fcoroutines-lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugaevc%2Fcoroutines-lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugaevc%2Fcoroutines-lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugaevc%2Fcoroutines-lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bugaevc","download_url":"https://codeload.github.com/bugaevc/coroutines-lite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244716890,"owners_count":20498277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T20:00:36.240Z","updated_at":"2025-03-21T00:29:54.959Z","avatar_url":"https://github.com/bugaevc.png","language":"Kotlin","readme":"# Kotlin Coroutines Lite\nThis is a lightweight coroutines library for Kotlin.\n\nLike the official [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines), this library implements a coroutines framework on top of the support for `suspend` functions provided by the Kotlin compiler. Coroutines Lite implements an API that is very similar (but not always identical) to _kotlinx.coroutines_.\n\nUnlike _kotlinx.coroutines_, this library is optimized for _clarity_ and _simplicity_, not safety or performance:\n\n* where _kotlinx.coroutines_ uses lock-free linked lists, Coroutines Lite uses `synchronized` with a simple list;\n* where _kotlinx.coroutines_ has many optimized fast paths, Coroutines Lite does not;\n* where _kotlinx.coroutines_ uses a public interface with multiple specialized private implementations, Coroutines Lite has just a single class;\n* where _kotlinx.coroutines_ has invariant-validating wrappers like `SafeCollector`, Coroutines Lite does things directly.\n\nIn other words, Coroutines Lite is suitable for experimenting and learning, while _kotlinx.coroutines_ is great for running in production.\n\n## Examples\n\nSpawning a thousand concurrent coroutines, each waiting for 100 ms and returning:\n\n```kotlin\nimport io.github.bugaevc.coroutineslite.*\n\nrunBlocking { \n    for (i in 1..1000) {\n        launch {\n            delay(timeMillis = 100)\n        }\n    }\n}\nprintln(\"All done!\")\n```\n\nRunning things concurrently, in a structured manner (parallel decomposition):\n\n```kotlin\nimport io.github.bugaevc.coroutineslite.*\n\nsuspend fun concurrencyDemo(): Pair\u003cLong, String\u003e {\n    // Open a coroutine scope. Inside the scope, we can spawn concurrent jobs.\n    // The scope will only complete once all the spawned jobs do.\n    return coroutineScope {\n        // Start the heavy computation on the default dispatcher, which is\n        // backed by a work-stealing thread pool whose size is determined\n        // by the number of CPU cores.\n        val computation: Deferred\u003cLong\u003e = async(Dispatchers.Default) {\n            // Do some complex, CPU-heavy computation.\n            heavyComputation()\n        }\n        // Start the blocking I/O on the I/O dispatcher, which is backed\n        // by the same thread pool, but informs it that the operations will\n        // block, which causes it to spawn more threads to compensate.\n        val io: Deferred\u003cString\u003e = async(Dispatchers.IO) {\n            // Do some blocking I/O that may block the calling\n            // thread for a long time.\n            blockingIO()\n        }\n        // Now wait for both operations to complete. The current thread is\n        // not blocked while we're waiting, and it can participate in the\n        // thread pool, alongside the other worker threads.\n        val computed: Long = computation.await()\n        val received: String = io.await()\n        // Both operations have completed successfully (otherwise, the calls\n        // above would throw an exception), so return the results.\n        computed to received\n    }\n}\n```\n\nFetching a list of things concurrently. Note that if any individual `fetchSomething()` call fails,\n\n1. All the other `fetchSomething()` calls will immediately get cancelled, along with the whole coroutine scope.\n2. The scope will wait for all the child jobs to fully complete, i.e. run any post-cancellation cleanup logic.\n3. `coroutineScope { }` (and thus `fetchAll()`) will re-throw the original exception.\n\n```kotlin\nimport io.github.bugaevc.coroutineslite.*\n\nsuspend fun fetchSomething(key: Int): String {\n    delay(1_000)\n    return \"value for $key\"\n}\n\nsuspend fun fetchAll(keys: List\u003cInt\u003e): List\u003cString\u003e {\n    return coroutineScope { \n        // Map each key to a Deferred\u003cString\u003e,\n        // then await them all concurrently.\n        keys.map { key -\u003e \n            async {\n                fetchSomething(key)\n            }\n        }.awaitAll()\n    }\n}\n```\n\nWorking with an asynchronous flow of values:\n\n```kotlin\nimport io.github.bugaevc.coroutineslite.*\nimport io.github.bugaevc.coroutineslite.flow.*\n\nflow\u003cInt\u003e { \n    delay(100)\n    emit(35)\n    delay(200)\n    emit(42)\n}.map { value -\u003e\n    withContext(Dispatchers.IO) {\n        someBlockingRequest(value)\n    }\n}.collect { value -\u003e\n    println(\"Collected $value\")\n}\n```\n\nWrapping a callback-based API into a `suspend fun`:\n\n```kotlin\nimport io.github.bugaevc.coroutineslite.*\nimport okhttp3.*\nimport java.io.IOException\nimport kotlin.coroutines.resumeWithException\n\n/**\n * Await an OkHttp call in a coroutine.\n */\nsuspend fun Call.await(): Response {\n    // Suspend us in a cancellable manner, and get a continuation that\n    // we can use to resume ourselves back once the response is ready.\n    return suspendCancellableCoroutine { continuation -\u003e\n        // Start the call with the following callback:\n        enqueue(responseCallback = object : okhttp3.Callback {\n            override fun onResponse(call: Call, response: Response) {\n                // The call succeeded, and yielded a response. Try to resume\n                // the coroutine. If it can't be resumed because it's already\n                // cancelled, make sure to close the response.\n                continuation.resume(response, onCancellation = {\n                    response.close()\n                })\n            }\n\n            override fun onFailure(call: Call, e: IOException) {\n                // The call failed; resume the coroutine with the error.\n                continuation.resumeWithException(e)\n            }\n        })\n        // If the coroutine gets cancelled, cancel the call as well.\n        continuation.invokeOnCancellation {\n            cancel()\n        }\n    }\n}\n```\n\nWrapping a multi-shot callback-based API into a flow using `channelFlow { }`:\n\n```kotlin\nimport io.github.bugaevc.coroutineslite.*\nimport io.github.bugaevc.coroutineslite.flow.*\n\nchannelFlow\u003cString\u003e { \n    SomeApi.registerCallback(object : SomeApi.Callback {\n        override fun onNewItem(item: String) {\n            // Send the new item through the channel,\n            // which will emit it form the flow. Block this\n            // thread in case the flow consumer cannot keep\n            // up with new items.\n            runBlocking(Dispatchers.Unconfined) {\n                send(item)\n            }\n        }\n\n        override fun onDone() {\n            // Close the channel; this indicates the end\n            // of the flow.\n            close()\n        }\n\n        override fun onError(ex: Throwable) {\n            // Close the channel with the error; this will\n            // cause the error to be propagated to the flow\n            // collector.\n            close(ex)\n        }\n    })\n    // Don't return from channelFlow { } until explicitly closed.\n    awaitClose()\n}\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbugaevc%2Fcoroutines-lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbugaevc%2Fcoroutines-lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbugaevc%2Fcoroutines-lite/lists"}