Skip to content

Instantly share code, notes, and snippets.

@GibsonRuitiari
Created February 11, 2024 21:27
Show Gist options
  • Save GibsonRuitiari/12cd16074d0d59422918ea837ed28984 to your computer and use it in GitHub Desktop.
Save GibsonRuitiari/12cd16074d0d59422918ea837ed28984 to your computer and use it in GitHub Desktop.
fun main(){
coroutineScope {
launch { findEvenNumbers(1,10..20) }
launch { findEvenNumbers(2,30..60) }
}
}
private fun findEvenNumbers(workerName:Int,range: IntRange){
for (i in range){
if (i%2==0) println("[$workerName]: even found $i")
}
}
/**
* A simple make-shift coroutine scope showing how you can schedule different jobs and make then run them in parallel
* (basically mimick
* Kotlin's coroutine scope in a simple way)
* This is to be used for learning purposes only
* Each job can have at least 5 states: done, failed, active, idle or started
* A job that is not doing anything is in its idle state
* a job that is on the onset of doing a certain task X is in on its active state
* a job that has succesfully completed its task X moves to its on done state
* and if the work was un-successful, the job moves to its on Failed state
* to clean up the jobs' states, the states are reset back to the initial state which is idle state
* to signify that the scope is ready to accept new jobs
* The scope is cooperative in that, all jobs must complete for the scope to complete. It is an 'all or nothing'
* scenario just like the Kotlin's coroutine-scope. If one job fails, all of the tasks will fail and the scope
* will be cleaned up/done away with
* Todo: maybe add a robust error handling and state mechanism?
*/
private typealias State =Int
private const val State_Done:State=1
private const val State_Failed:State=2
private const val State_Active:State=3
private const val State_Idle:State=4
private const val State_Job_Started:State=5
@DslMarker
annotation class Scope
@Scope
class CoroutineScope{
private val jobs = mutableListOf<()->Unit>()
private val jobStates = mutableMapOf<Int,State>()
infix fun launch(job:()->Unit){
jobs.add(job)
}
fun batchPerformWork(){
val barrier = CyclicBarrier(jobs.size)
markJobsAsStarted()
dumpJobsStates()
try{
for ((index,job) in jobs.withIndex()){
jobStates[index] = State_Active
dumpJobState(index)
thread {
job()
barrier.await()
}
jobStates[index]= State_Done
dumpJobState(index)
}
}catch (_:InterruptedException){
markJobsAsFailed()
}
catch (_:TimeoutException){
markJobsAsFailed()
}
catch (_:IOException){
markJobsAsFailed()
}
// clean up
finally{
markJobsAsIdle()
dumpJobsStates()
}
}
private fun dumpJobsStates(){
for ((i,_) in jobStates){
dumpJobState(i)
}
}
private fun markJobsAsStarted(){
for (i in jobs.indices){
jobStates[i] = State_Job_Started
}
}
private fun markJobsAsIdle(){
for (i in jobs.indices){
jobStates[i] = State_Idle
}
}
private fun markJobsAsFailed(){
for (i in jobs.indices){
jobStates[i] = State_Failed
}
}
private fun dumpJobState(index:Int){
val state = jobStates[index]
val stateMsg=when(state){
State_Idle->"job[$index] > Idle"
State_Job_Started->"job[$index] > JobStarted"
State_Active->"job[$index] > Active"
State_Failed->"job[$index] > Failed"
State_Done->"job[$index] > Done"
else->"Unknown state?"
}
println(stateMsg)
}
}
fun coroutineScope(block:CoroutineScope.()->Unit){
val scope = CoroutineScope().apply(block)
scope.batchPerformWork()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment