Skip to content

Commit 440e848

Browse files
committed
refactor: update extension functions
1 parent 137c72e commit 440e848

File tree

4 files changed

+82
-44
lines changed

4 files changed

+82
-44
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ But unlike `SharedPreferences`, there's no `apply()` or `commit()`. Changes are
114114
### Threading
115115
PufferDB uses a [ConcurrentHashMap](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html) to manage a thread-safe in-memory cache for fast read and write operations.
116116

117-
Changes are saved asynchronously with the help of a [Conflated Channel](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/index.html) (to save the most recent state in a race condition) and [Mutex](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html) locker (to prevent simultaneous writes).
117+
Changes are saved asynchronously with the help of a [StateFlow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/index.html) (to save the most recent state in a race condition) and [Mutex](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html) locker (to prevent simultaneous writes).
118118

119-
It is possible to run the API methods on the Android Main Thread, but you should *avoid that*. You can use one of the wrapper modules or built in extension functions for that.
119+
It is possible to run the API methods on the Android Main Thread, but you should *avoid that*. You can use one of the wrapper modules or built in extension functions for that (listed below).
120120

121121
## Android
122122
The Android module contains an `AndroidPufferDB` helper class:
@@ -182,10 +182,9 @@ launch {
182182

183183
val myValue = getAsync<String>("myKey").await()
184184

185-
// You can use your custom coroutine context...
186-
putSuspend("myOtherKey", 123, Dispatchers.Unconfined)
185+
// You can use your own coroutine scope and dispatcher
186+
putSuspend("myOtherKey", 123, myCoroutineScope, myCoroutineDispatcher)
187187

188-
// ... And your custom coroutine scope
189188
putAsync("myOtherKey", 123, myActivityScope).await()
190189
}
191190
}

coroutines/src/main/kotlin/cafe/adriel/pufferdb/coroutines/CoroutineExtensions.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ package cafe.adriel.pufferdb.coroutines
22

33
import kotlin.coroutines.CoroutineContext
44
import kotlinx.coroutines.CoroutineScope
5-
import kotlinx.coroutines.Dispatchers
6-
import kotlinx.coroutines.GlobalScope
75
import kotlinx.coroutines.async
86
import kotlinx.coroutines.withContext
97

10-
internal suspend fun <T> runSuspend(context: CoroutineContext? = null, body: suspend CoroutineScope.() -> T) =
11-
withContext(context ?: Dispatchers.IO) { body() }
8+
internal suspend fun <T> runSuspend(
9+
context: CoroutineContext,
10+
body: suspend CoroutineScope.() -> T
11+
) =
12+
withContext(context) { body() }
1213

13-
internal fun <T> runAsync(scope: CoroutineScope? = null, body: suspend CoroutineScope.() -> T) =
14-
(scope ?: GlobalScope).async { body() }
14+
internal fun <T> runAsync(
15+
scope: CoroutineScope,
16+
dispatcher: CoroutineContext,
17+
body: suspend CoroutineScope.() -> T
18+
) =
19+
scope.async(dispatcher) { body() }

coroutines/src/main/kotlin/cafe/adriel/pufferdb/coroutines/CoroutinePufferDB.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import kotlinx.coroutines.GlobalScope
1010
class CoroutinePufferDB private constructor(
1111
pufferFile: File,
1212
scope: CoroutineScope,
13-
dispatcher: CoroutineContext
13+
private val dispatcher: CoroutineContext
1414
) : CoroutinePuffer {
1515

1616
companion object {
@@ -28,15 +28,21 @@ class CoroutinePufferDB private constructor(
2828

2929
private val puffer by lazy { PufferDB.with(pufferFile, scope, dispatcher) }
3030

31-
override suspend fun <T : Any> get(key: String, defaultValue: T?) = puffer.suspendGet(key, defaultValue)
31+
override suspend fun <T : Any> get(key: String, defaultValue: T?) =
32+
puffer.getSuspend(key, defaultValue, dispatcher)
3233

33-
override suspend fun <T : Any> put(key: String, value: T) = puffer.suspendPut(key, value)
34+
override suspend fun <T : Any> put(key: String, value: T) =
35+
puffer.putSuspend(key, value, dispatcher)
3436

35-
override suspend fun getKeys(): Set<String> = puffer.suspendGetKeys()
37+
override suspend fun getKeys(): Set<String> =
38+
puffer.getKeysSuspend(dispatcher)
3639

37-
override suspend fun contains(key: String) = puffer.suspendContains(key)
40+
override suspend fun contains(key: String) =
41+
puffer.containsSuspend(key, dispatcher)
3842

39-
override suspend fun remove(key: String) = puffer.suspendRemove(key)
43+
override suspend fun remove(key: String) =
44+
puffer.removeSuspend(key, dispatcher)
4045

41-
override suspend fun removeAll() = puffer.suspendRemoveAll()
46+
override suspend fun removeAll() =
47+
puffer.removeAllSuspend(dispatcher)
4248
}

coroutines/src/main/kotlin/cafe/adriel/pufferdb/coroutines/PufferExtensions.kt

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,71 @@ package cafe.adriel.pufferdb.coroutines
33
import cafe.adriel.pufferdb.core.Puffer
44
import kotlin.coroutines.CoroutineContext
55
import kotlinx.coroutines.CoroutineScope
6+
import kotlinx.coroutines.Dispatchers
7+
import kotlinx.coroutines.GlobalScope
68

79
// Suspend functions
10+
suspend fun <T : Any> Puffer.getSuspend(
11+
key: String,
12+
defaultValue: T? = null,
13+
dispatcher: CoroutineContext = Dispatchers.IO
14+
) =
15+
runSuspend(dispatcher) { get(key, defaultValue) }
816

9-
suspend fun <T : Any> Puffer.suspendGet(key: String, defaultValue: T? = null, context: CoroutineContext? = null) =
10-
runSuspend(context) { get(key, defaultValue) }
17+
suspend fun <T : Any> Puffer.putSuspend(key: String, value: T, dispatcher: CoroutineContext = Dispatchers.IO) =
18+
runSuspend(dispatcher) { put(key, value) }
1119

12-
suspend fun <T : Any> Puffer.suspendPut(key: String, value: T, context: CoroutineContext? = null) =
13-
runSuspend(context) { put(key, value) }
20+
suspend fun Puffer.getKeysSuspend(dispatcher: CoroutineContext = Dispatchers.IO) =
21+
runSuspend(dispatcher) { getKeys() }
1422

15-
suspend fun Puffer.suspendGetKeys(context: CoroutineContext? = null) =
16-
runSuspend(context) { getKeys() }
23+
suspend fun Puffer.containsSuspend(key: String, dispatcher: CoroutineContext = Dispatchers.IO) =
24+
runSuspend(dispatcher) { contains(key) }
1725

18-
suspend fun Puffer.suspendContains(key: String, context: CoroutineContext? = null) =
19-
runSuspend(context) { contains(key) }
26+
suspend fun Puffer.removeSuspend(key: String, dispatcher: CoroutineContext = Dispatchers.IO) =
27+
runSuspend(dispatcher) { remove(key) }
2028

21-
suspend fun Puffer.suspendRemove(key: String, context: CoroutineContext? = null) =
22-
runSuspend(context) { remove(key) }
23-
24-
suspend fun Puffer.suspendRemoveAll(context: CoroutineContext? = null) =
25-
runSuspend(context) { removeAll() }
29+
suspend fun Puffer.removeAllSuspend(dispatcher: CoroutineContext = Dispatchers.IO) =
30+
runSuspend(dispatcher) { removeAll() }
2631

2732
// Async functions
33+
fun <T : Any> Puffer.getAsync(
34+
key: String,
35+
defaultValue: T? = null,
36+
scope: CoroutineScope = GlobalScope,
37+
dispatcher: CoroutineContext = Dispatchers.IO
38+
) =
39+
runAsync(scope, dispatcher) { get(key, defaultValue) }
2840

29-
fun <T : Any> Puffer.getAsync(key: String, defaultValue: T? = null, scope: CoroutineScope? = null) =
30-
runAsync(scope) { get(key, defaultValue) }
31-
32-
fun <T : Any> Puffer.putAsync(key: String, value: T, scope: CoroutineScope? = null) =
33-
runAsync(scope) { put(key, value) }
41+
fun <T : Any> Puffer.putAsync(
42+
key: String,
43+
value: T,
44+
scope: CoroutineScope = GlobalScope,
45+
dispatcher: CoroutineContext = Dispatchers.IO
46+
) =
47+
runAsync(scope, dispatcher) { put(key, value) }
3448

35-
fun Puffer.getKeysAsync(scope: CoroutineScope? = null) =
36-
runAsync(scope) { getKeys() }
49+
fun Puffer.getKeysAsync(
50+
scope: CoroutineScope = GlobalScope,
51+
dispatcher: CoroutineContext = Dispatchers.IO
52+
) =
53+
runAsync(scope, dispatcher) { getKeys() }
3754

38-
fun Puffer.containsAsync(key: String, scope: CoroutineScope? = null) =
39-
runAsync(scope) { contains(key) }
55+
fun Puffer.containsAsync(
56+
key: String,
57+
scope: CoroutineScope = GlobalScope,
58+
dispatcher: CoroutineContext = Dispatchers.IO
59+
) =
60+
runAsync(scope, dispatcher) { contains(key) }
4061

41-
fun Puffer.removeAsync(key: String, scope: CoroutineScope? = null) =
42-
runAsync(scope) { remove(key) }
62+
fun Puffer.removeAsync(
63+
key: String,
64+
scope: CoroutineScope = GlobalScope,
65+
dispatcher: CoroutineContext = Dispatchers.IO
66+
) =
67+
runAsync(scope, dispatcher) { remove(key) }
4368

44-
fun Puffer.removeAllAsync(scope: CoroutineScope? = null) =
45-
runAsync(scope) { removeAll() }
69+
fun Puffer.removeAllAsync(
70+
scope: CoroutineScope = GlobalScope,
71+
dispatcher: CoroutineContext = Dispatchers.IO
72+
) =
73+
runAsync(scope, dispatcher) { removeAll() }

0 commit comments

Comments
 (0)