Skip to content

Commit c16123e

Browse files
committed
WIP Add coroutines examples
1 parent e2c90c8 commit c16123e

38 files changed

+2456
-13
lines changed

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@
2020

2121
### Metrics
2222
```text
23-
15288 number of properties
24-
10573 number of functions
25-
8954 number of classes
26-
240 number of packages
27-
3543 number of kt files
23+
15600 number of properties
24+
10708 number of functions
25+
9006 number of classes
26+
241 number of packages
27+
3579 number of kt files
2828
```
2929

3030

3131
### Complexity Report
3232
```text
33-
267458 lines of code (loc)
34-
166374 source lines of code (sloc)
35-
121548 logical lines of code (lloc)
36-
72562 comment lines of code (cloc)
37-
25100 cyclomatic complexity (mcc)
38-
20431 cognitive complexity
33+
270027 lines of code (loc)
34+
168414 source lines of code (sloc)
35+
122999 logical lines of code (lloc)
36+
72635 comment lines of code (cloc)
37+
25394 cyclomatic complexity (mcc)
38+
20712 cognitive complexity
3939
0 number of total code smells
4040
43 comment source ratio
4141
206 mcc per 1,000 lloc
42-
```
42+
```

api/Kotlin-Lab.api

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20091,6 +20091,170 @@ public final class dev/shtanko/concurrency/coroutines/sort/CoroutinesMergeSort {
2009120091
public static synthetic fun perform$default (Ldev/shtanko/concurrency/coroutines/sort/CoroutinesMergeSort;[IIILjava/lang/Object;)[I
2009220092
}
2009320093

20094+
public abstract class dev/shtanko/concurrency/coroutines/tasks/BaseTask : dev/shtanko/concurrency/coroutines/tasks/Task {
20095+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lkotlinx/coroutines/CoroutineDispatcher;)V
20096+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Lkotlinx/coroutines/CoroutineDispatcher;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
20097+
public fun cancel ()V
20098+
protected abstract fun execute (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
20099+
public fun getDescription ()Ljava/lang/String;
20100+
public fun getName ()Ljava/lang/String;
20101+
public fun getProgress ()Lkotlinx/coroutines/flow/StateFlow;
20102+
public fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
20103+
public fun run (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
20104+
protected final fun updateProgress (F)V
20105+
protected final fun updateStatus (Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;)V
20106+
}
20107+
20108+
public final class dev/shtanko/concurrency/coroutines/tasks/BinaryTreeTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20109+
public fun <init> ()V
20110+
public fun <init> (I)V
20111+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20112+
}
20113+
20114+
public final class dev/shtanko/concurrency/coroutines/tasks/BinaryTreeTask$TreeNode {
20115+
public fun <init> (I)V
20116+
public final fun getLeft ()Ldev/shtanko/concurrency/coroutines/tasks/BinaryTreeTask$TreeNode;
20117+
public final fun getRight ()Ldev/shtanko/concurrency/coroutines/tasks/BinaryTreeTask$TreeNode;
20118+
public final fun getValue ()I
20119+
public final fun setLeft (Ldev/shtanko/concurrency/coroutines/tasks/BinaryTreeTask$TreeNode;)V
20120+
public final fun setRight (Ldev/shtanko/concurrency/coroutines/tasks/BinaryTreeTask$TreeNode;)V
20121+
}
20122+
20123+
public final class dev/shtanko/concurrency/coroutines/tasks/CompressionTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20124+
public fun <init> ()V
20125+
public fun <init> (I)V
20126+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20127+
}
20128+
20129+
public final class dev/shtanko/concurrency/coroutines/tasks/CryptographicTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20130+
public fun <init> ()V
20131+
public fun <init> (I)V
20132+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20133+
}
20134+
20135+
public final class dev/shtanko/concurrency/coroutines/tasks/GraphAlgorithmsTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20136+
public fun <init> ()V
20137+
public fun <init> (I)V
20138+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20139+
}
20140+
20141+
public final class dev/shtanko/concurrency/coroutines/tasks/HashComputationTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20142+
public fun <init> ()V
20143+
public fun <init> (I)V
20144+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20145+
}
20146+
20147+
public final class dev/shtanko/concurrency/coroutines/tasks/ImageProcessingTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20148+
public fun <init> ()V
20149+
public fun <init> (II)V
20150+
public synthetic fun <init> (IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
20151+
}
20152+
20153+
public final class dev/shtanko/concurrency/coroutines/tasks/MainKt {
20154+
public static final fun main ()V
20155+
public static synthetic fun main ([Ljava/lang/String;)V
20156+
}
20157+
20158+
public final class dev/shtanko/concurrency/coroutines/tasks/MandelbrotTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20159+
public fun <init> ()V
20160+
public fun <init> (III)V
20161+
public synthetic fun <init> (IIIILkotlin/jvm/internal/DefaultConstructorMarker;)V
20162+
}
20163+
20164+
public final class dev/shtanko/concurrency/coroutines/tasks/MatrixMultiplicationTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20165+
public fun <init> ()V
20166+
public fun <init> (I)V
20167+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20168+
}
20169+
20170+
public final class dev/shtanko/concurrency/coroutines/tasks/MergeSortTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20171+
public fun <init> ()V
20172+
public fun <init> (ILkotlinx/coroutines/CoroutineDispatcher;)V
20173+
public synthetic fun <init> (ILkotlinx/coroutines/CoroutineDispatcher;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
20174+
}
20175+
20176+
public final class dev/shtanko/concurrency/coroutines/tasks/NeuralNetworkTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20177+
public fun <init> ()V
20178+
public fun <init> (IIII)V
20179+
public synthetic fun <init> (IIIIILkotlin/jvm/internal/DefaultConstructorMarker;)V
20180+
}
20181+
20182+
public final class dev/shtanko/concurrency/coroutines/tasks/PrimeCalculationTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20183+
public fun <init> ()V
20184+
public fun <init> (ILkotlinx/coroutines/CoroutineDispatcher;)V
20185+
public synthetic fun <init> (ILkotlinx/coroutines/CoroutineDispatcher;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
20186+
}
20187+
20188+
public final class dev/shtanko/concurrency/coroutines/tasks/QuickSortTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20189+
public fun <init> ()V
20190+
public fun <init> (ILkotlinx/coroutines/CoroutineDispatcher;)V
20191+
public synthetic fun <init> (ILkotlinx/coroutines/CoroutineDispatcher;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
20192+
}
20193+
20194+
public final class dev/shtanko/concurrency/coroutines/tasks/SortingTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20195+
public fun <init> ()V
20196+
public fun <init> (I)V
20197+
public synthetic fun <init> (IILkotlin/jvm/internal/DefaultConstructorMarker;)V
20198+
}
20199+
20200+
public final class dev/shtanko/concurrency/coroutines/tasks/StringMatchingTask : dev/shtanko/concurrency/coroutines/tasks/BaseTask {
20201+
public fun <init> ()V
20202+
public fun <init> (II)V
20203+
public synthetic fun <init> (IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
20204+
}
20205+
20206+
public abstract interface class dev/shtanko/concurrency/coroutines/tasks/Task {
20207+
public abstract fun cancel ()V
20208+
public abstract fun getDescription ()Ljava/lang/String;
20209+
public abstract fun getName ()Ljava/lang/String;
20210+
public abstract fun getProgress ()Lkotlinx/coroutines/flow/StateFlow;
20211+
public abstract fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
20212+
public abstract fun run (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
20213+
}
20214+
20215+
public final class dev/shtanko/concurrency/coroutines/tasks/TaskResult {
20216+
public fun <init> (Ljava/lang/String;Ljava/lang/Object;JLdev/shtanko/concurrency/coroutines/tasks/TaskStatus;)V
20217+
public final fun component1 ()Ljava/lang/String;
20218+
public final fun component2 ()Ljava/lang/Object;
20219+
public final fun component3 ()J
20220+
public final fun component4 ()Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20221+
public final fun copy (Ljava/lang/String;Ljava/lang/Object;JLdev/shtanko/concurrency/coroutines/tasks/TaskStatus;)Ldev/shtanko/concurrency/coroutines/tasks/TaskResult;
20222+
public static synthetic fun copy$default (Ldev/shtanko/concurrency/coroutines/tasks/TaskResult;Ljava/lang/String;Ljava/lang/Object;JLdev/shtanko/concurrency/coroutines/tasks/TaskStatus;ILjava/lang/Object;)Ldev/shtanko/concurrency/coroutines/tasks/TaskResult;
20223+
public fun equals (Ljava/lang/Object;)Z
20224+
public final fun getExecutionTime ()J
20225+
public final fun getResult ()Ljava/lang/Object;
20226+
public final fun getStatus ()Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20227+
public final fun getTaskName ()Ljava/lang/String;
20228+
public fun hashCode ()I
20229+
public fun toString ()Ljava/lang/String;
20230+
}
20231+
20232+
public final class dev/shtanko/concurrency/coroutines/tasks/TaskStatus : java/lang/Enum {
20233+
public static final field CANCELLED Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20234+
public static final field COMPLETED Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20235+
public static final field ERROR Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20236+
public static final field IDLE Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20237+
public static final field RUNNING Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20238+
public static fun getEntries ()Lkotlin/enums/EnumEntries;
20239+
public static fun valueOf (Ljava/lang/String;)Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20240+
public static fun values ()[Ldev/shtanko/concurrency/coroutines/tasks/TaskStatus;
20241+
}
20242+
20243+
public final class dev/shtanko/concurrency/coroutines/tasks/TaskViewModel {
20244+
public fun <init> ()V
20245+
public fun <init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
20246+
public synthetic fun <init> (Lkotlinx/coroutines/CoroutineDispatcher;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
20247+
public final fun addTask (Ldev/shtanko/concurrency/coroutines/tasks/Task;)V
20248+
public final fun cancelAllTasks ()V
20249+
public final fun clearResults ()V
20250+
public final fun clearTasks ()V
20251+
public final fun getResults ()Lkotlinx/coroutines/flow/StateFlow;
20252+
public final fun getTasks ()Lkotlinx/coroutines/flow/StateFlow;
20253+
public final fun onCleared ()V
20254+
public final fun runAllTasks ()V
20255+
public final fun runTask (Ldev/shtanko/concurrency/coroutines/tasks/Task;)V
20256+
}
20257+
2009420258
public final class dev/shtanko/concurrency/jvm/deadlock/DeadLockSample {
2009520259
public static final field INSTANCE Ldev/shtanko/concurrency/jvm/deadlock/DeadLockSample;
2009620260
public static final fun main ([Ljava/lang/String;)V

config/main.md.bak

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<a href="https://hitsofcode.com/github/ashtanko/kotlab/view?branch=main"><img alt="Hits-of-Code" src="https://hitsofcode.com/github/ashtanko/kotlab?branch=main"/></a>
1111
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fashtanko%2Falgorithms-in-depth?ref=badge_shield&issueType=license"><img alt="FOSSA Status" src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fashtanko%2Falgorithms-in-depth.svg?type=shield&issueType=license"/></a>
1212
<a href="https://ktlint.github.io/"><img alt="CodeStyle" src="https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg"/></a>
13-
<a href="https://kotlinlang.org/"><img alt="Kotlin Version" src="https://img.shields.io/badge/kotlin-2.2.0-blue.svg"/></a>
13+
<a href="https://kotlinlang.org/"><img alt="Kotlin Version" src="https://img.shields.io/badge/kotlin-2.2.10-blue.svg"/></a>
1414
<a href="https://sonarcloud.io/summary/new_code?id=ashtanko_kotlab"><img alt="Quality Gate Status" src="https://sonarcloud.io/api/project_badges/measure?project=ashtanko_kotlab&metric=alert_status"/></a>
1515
<a href="https://sonarcloud.io/summary/new_code?id=ashtanko_kotlab"><img alt="Bugs" src="https://sonarcloud.io/api/project_badges/measure?project=ashtanko_kotlab&metric=bugs"/></a>
1616
<a href="https://sonarcloud.io/summary/new_code?id=ashtanko_kotlab"><img alt="Code Smells" src="https://sonarcloud.io/api/project_badges/measure?project=ashtanko_kotlab&metric=code_smells"/></a>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dev.shtanko.concurrency.coroutines.tasks
2+
3+
import kotlin.coroutines.cancellation.CancellationException
4+
import kotlinx.coroutines.CoroutineDispatcher
5+
import kotlinx.coroutines.Dispatchers
6+
import kotlinx.coroutines.Job
7+
import kotlinx.coroutines.flow.MutableStateFlow
8+
import kotlinx.coroutines.flow.StateFlow
9+
import kotlinx.coroutines.flow.asStateFlow
10+
import kotlinx.coroutines.withContext
11+
12+
@Suppress("TooGenericExceptionCaught")
13+
abstract class BaseTask<R>(
14+
override val name: String,
15+
override val description: String,
16+
private val dispatcher: CoroutineDispatcher = Dispatchers.Default,
17+
) : Task<R> {
18+
private val _progress = MutableStateFlow(0f)
19+
override val progress: StateFlow<Float> = _progress.asStateFlow()
20+
21+
private val _status = MutableStateFlow(TaskStatus.IDLE)
22+
override val status: StateFlow<TaskStatus> = _status.asStateFlow()
23+
24+
private var job: Job? = null
25+
26+
protected fun updateProgress(value: Float) {
27+
_progress.value = value.coerceIn(0f, 1f)
28+
}
29+
30+
protected fun updateStatus(status: TaskStatus) {
31+
_status.value = status
32+
}
33+
34+
override fun cancel() {
35+
job?.cancel()
36+
updateStatus(TaskStatus.CANCELLED)
37+
}
38+
39+
override suspend fun run(): R {
40+
return withContext(dispatcher) {
41+
job = coroutineContext[Job]
42+
updateStatus(TaskStatus.RUNNING)
43+
updateProgress(0f)
44+
45+
try {
46+
val result = execute()
47+
updateStatus(TaskStatus.COMPLETED)
48+
updateProgress(1f)
49+
result
50+
} catch (e: CancellationException) {
51+
updateStatus(TaskStatus.CANCELLED)
52+
throw e
53+
} catch (e: Exception) {
54+
updateStatus(TaskStatus.ERROR)
55+
throw e
56+
}
57+
}
58+
}
59+
60+
protected abstract suspend fun execute(): R
61+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
@file:Suppress("MagicNumber")
2+
3+
package dev.shtanko.concurrency.coroutines.tasks
4+
5+
import kotlin.random.Random
6+
import kotlinx.coroutines.yield
7+
8+
class BinaryTreeTask(
9+
private val nodeCount: Int = 50_000,
10+
) : BaseTask<String>(
11+
name = "Binary Tree Operations",
12+
description = "Building and traversing $nodeCount nodes",
13+
) {
14+
class TreeNode(val value: Int) {
15+
var left: TreeNode? = null
16+
var right: TreeNode? = null
17+
}
18+
19+
override suspend fun execute(): String {
20+
var root: TreeNode? = null
21+
val values = List(nodeCount) { Random.nextInt(1000000) }
22+
23+
// Build tree
24+
for ((index, value) in values.withIndex()) {
25+
if (index % 500 == 0) {
26+
yield()
27+
updateProgress(index.toFloat() / (nodeCount * 2))
28+
}
29+
root = insert(root, value)
30+
}
31+
32+
// Calculate tree properties
33+
val height = calculateHeight(root)
34+
val nodeSum = sumNodes(root)
35+
36+
return "Height: $height, Sum: $nodeSum"
37+
}
38+
39+
private fun insert(root: TreeNode?, value: Int): TreeNode {
40+
if (root == null) return TreeNode(value)
41+
42+
if (value < root.value) {
43+
root.left = insert(root.left, value)
44+
} else {
45+
root.right = insert(root.right, value)
46+
}
47+
return root
48+
}
49+
50+
private suspend fun calculateHeight(node: TreeNode?): Int {
51+
if (node == null) return 0
52+
return 1 + maxOf(calculateHeight(node.left), calculateHeight(node.right))
53+
}
54+
55+
private suspend fun sumNodes(node: TreeNode?): Long {
56+
if (node == null) return 0
57+
return node.value + sumNodes(node.left) + sumNodes(node.right)
58+
}
59+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@file:Suppress("MagicNumber")
2+
3+
package dev.shtanko.concurrency.coroutines.tasks
4+
5+
import kotlin.random.Random
6+
import kotlinx.coroutines.yield
7+
8+
class CompressionTask(
9+
private val dataSize: Int = 100_000,
10+
) : BaseTask<Double>(
11+
name = "Data Compression",
12+
description = "LZ77 compression of $dataSize bytes",
13+
) {
14+
override suspend fun execute(): Double {
15+
val data = ByteArray(dataSize) { (Random.nextInt(26) + 'a'.code).toByte() }
16+
val compressed = mutableListOf<Triple<Int, Int, Byte>>() // (offset, length, next char)
17+
18+
var i = 0
19+
while (i < data.size) {
20+
if (i % 1000 == 0) {
21+
yield()
22+
updateProgress(i.toFloat() / dataSize)
23+
}
24+
25+
var maxLength = 0
26+
var maxOffset = 0
27+
val searchStart = maxOf(0, i - 4096) // Search window
28+
29+
for (j in searchStart until i) {
30+
var length = 0
31+
while (i + length < data.size &&
32+
length < 255 &&
33+
data[j + length] == data[i + length]
34+
) {
35+
length++
36+
}
37+
38+
if (length > maxLength) {
39+
maxLength = length
40+
maxOffset = i - j
41+
}
42+
}
43+
44+
val nextChar = if (i + maxLength < data.size) data[i + maxLength] else 0
45+
compressed.add(Triple(maxOffset, maxLength, nextChar))
46+
i += maxLength + 1
47+
}
48+
49+
val compressionRatio = compressed.size * 3.0 / dataSize
50+
return compressionRatio
51+
}
52+
}

0 commit comments

Comments
 (0)