Created
February 11, 2024 21:27
-
-
Save GibsonRuitiari/12cd16074d0d59422918ea837ed28984 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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