Skip to content

Commit 12358a7

Browse files
committed
Add lock parameter
1 parent 02fa66c commit 12358a7

File tree

9 files changed

+56
-30
lines changed

9 files changed

+56
-30
lines changed

cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CacheStoreClassDeclaration.kt

+10-7
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,30 @@ class CacheStoreClassDeclaration(
3232

3333
private val irConstructorSymbol: IrConstructorSymbol
3434
get() = irClassSymbol.constructors.single {
35-
it.owner.valueParameters.size == 1 &&
36-
it.owner.valueParameters.first().type == irBuiltIns.intType
35+
it.owner.valueParameters.size == 2 &&
36+
it.owner.valueParameters[0].type == irBuiltIns.intType &&
37+
it.owner.valueParameters[1].type == irBuiltIns.booleanType
3738
}
3839

3940
private val irCacheOrInvokeFunctionSymbol: IrSimpleFunctionSymbol
4041
get() = irClassSymbol.functions
4142
.single { it.owner.name == cacheOrInvokedFunctionName }
4243

43-
fun createConstructorCall(maxCountExpression: IrExpression?): IrConstructorCall {
44+
fun createConstructorCall(
45+
maxCountExpression: IrExpression?,
46+
lockExpression: IrExpression?,
47+
): IrConstructorCall {
4448
val call = IrConstructorCallImpl(
4549
startOffset = UNDEFINED_OFFSET,
4650
endOffset = UNDEFINED_OFFSET,
4751
type = irType,
4852
symbol = irConstructorSymbol,
4953
typeArgumentsCount = 0,
5054
constructorTypeArgumentsCount = 0,
51-
valueArgumentsCount = 1,
55+
valueArgumentsCount = 2,
5256
)
53-
if (maxCountExpression != null) {
54-
call.putValueArgument(0, maxCountExpression)
55-
}
57+
call.putValueArgument(0, maxCountExpression)
58+
call.putValueArgument(1, lockExpression)
5659
return call
5760
}
5861

cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CacheableAnnotationDeclaration.kt

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ class CacheableAnnotationDeclaration {
1414
fun findMaxCountExpression(annotationContainer: IrAnnotationContainer): IrExpression? =
1515
annotationContainer.getAnnotation(name)
1616
?.valueArguments
17-
?.firstOrNull()
17+
?.getOrNull(0)
18+
19+
fun findLockExpression(annotationContainer: IrAnnotationContainer): IrExpression? =
20+
annotationContainer.getAnnotation(name)
21+
?.valueArguments
22+
?.getOrNull(1)
1823

1924
companion object {
2025
val name = FqName("com.moriatsushi.cacheable.Cacheable")

cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CacheableDeclarations.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
55
class CacheableDeclarations(
66
val cacheableAnnotationDeclaration: CacheableAnnotationDeclaration,
77
val cacheStoreClassDeclaration: CacheStoreClassDeclaration,
8-
val suspendCacheStoreClassDeclaration: SuspendCacheStoreClassDeclaration,
8+
val coroutineCacheStoreClassDeclaration: CoroutineCacheStoreClassDeclaration,
99
) {
1010
companion object {
1111
fun find(pluginContext: IrPluginContext): CacheableDeclarations? {
1212
val cacheStoreClassDeclaration =
1313
CacheStoreClassDeclaration.find(pluginContext) ?: return null
14-
val suspendCacheStoreClassDeclaration =
15-
SuspendCacheStoreClassDeclaration.find(pluginContext) ?: return null
14+
val coroutineCacheStoreClassDeclaration =
15+
CoroutineCacheStoreClassDeclaration.find(pluginContext) ?: return null
1616

1717
return CacheableDeclarations(
1818
CacheableAnnotationDeclaration(),
1919
cacheStoreClassDeclaration,
20-
suspendCacheStoreClassDeclaration,
20+
coroutineCacheStoreClassDeclaration,
2121
)
2222
}
2323
}
+13-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.name.ClassId
2323
import org.jetbrains.kotlin.name.FqName
2424
import org.jetbrains.kotlin.name.Name
2525

26-
class SuspendCacheStoreClassDeclaration(
26+
class CoroutineCacheStoreClassDeclaration(
2727
private val irClassSymbol: IrClassSymbol,
2828
private val irBuiltIns: IrBuiltIns,
2929
) {
@@ -32,27 +32,30 @@ class SuspendCacheStoreClassDeclaration(
3232

3333
private val irConstructorSymbol: IrConstructorSymbol
3434
get() = irClassSymbol.constructors.single {
35-
it.owner.valueParameters.size == 1 &&
36-
it.owner.valueParameters.first().type == irBuiltIns.intType
35+
it.owner.valueParameters.size == 2 &&
36+
it.owner.valueParameters[0].type == irBuiltIns.intType &&
37+
it.owner.valueParameters[1].type == irBuiltIns.booleanType
3738
}
3839

3940
private val irCacheOrInvokeFunctionSymbol: IrSimpleFunctionSymbol
4041
get() = irClassSymbol.functions
4142
.single { it.owner.name == cacheOrInvokedFunctionName }
4243

43-
fun createConstructorCall(maxCountExpression: IrExpression?): IrConstructorCall {
44+
fun createConstructorCall(
45+
maxCountExpression: IrExpression?,
46+
lockExpression: IrExpression?,
47+
): IrConstructorCall {
4448
val call = IrConstructorCallImpl(
4549
startOffset = UNDEFINED_OFFSET,
4650
endOffset = UNDEFINED_OFFSET,
4751
type = irType,
4852
symbol = irConstructorSymbol,
4953
typeArgumentsCount = 0,
5054
constructorTypeArgumentsCount = 0,
51-
valueArgumentsCount = 1,
55+
valueArgumentsCount = 2,
5256
)
53-
if (maxCountExpression != null) {
54-
call.putValueArgument(0, maxCountExpression)
55-
}
57+
call.putValueArgument(0, maxCountExpression)
58+
call.putValueArgument(1, lockExpression)
5659
return call
5760
}
5861

@@ -90,9 +93,9 @@ class SuspendCacheStoreClassDeclaration(
9093
ClassId(internalPackageName, Name.identifier("CoroutineCacheStore"))
9194
private val cacheOrInvokedFunctionName = Name.identifier("cacheOrInvoke")
9295

93-
fun find(pluginContext: IrPluginContext): SuspendCacheStoreClassDeclaration? =
96+
fun find(pluginContext: IrPluginContext): CoroutineCacheStoreClassDeclaration? =
9497
pluginContext.referenceClass(cacheStoreId)?.let {
95-
SuspendCacheStoreClassDeclaration(it, pluginContext.irBuiltIns)
98+
CoroutineCacheStoreClassDeclaration(it, pluginContext.irBuiltIns)
9699
}
97100
}
98101
}

cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/factory/IrCacheStoreFieldFactory.kt

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class IrCacheStoreFieldFactory(
1919
val field = irFactory.buildField {
2020
name = Name.identifier(function.name.identifier + CACHE_STORE_SUFFIX)
2121
type = if (function.isSuspend) {
22-
cacheableDeclarations.suspendCacheStoreClassDeclaration.irType
22+
cacheableDeclarations.coroutineCacheStoreClassDeclaration.irType
2323
} else {
2424
cacheableDeclarations.cacheStoreClassDeclaration.irType
2525
}
@@ -28,12 +28,14 @@ class IrCacheStoreFieldFactory(
2828
}
2929
val maxCountExpression = cacheableDeclarations.cacheableAnnotationDeclaration
3030
.findMaxCountExpression(function)
31+
val lockExpression = cacheableDeclarations.cacheableAnnotationDeclaration
32+
.findLockExpression(function)
3133
val constructorCall = if (function.isSuspend) {
32-
cacheableDeclarations.suspendCacheStoreClassDeclaration
33-
.createConstructorCall(maxCountExpression)
34+
cacheableDeclarations.coroutineCacheStoreClassDeclaration
35+
.createConstructorCall(maxCountExpression, lockExpression)
3436
} else {
3537
cacheableDeclarations.cacheStoreClassDeclaration
36-
.createConstructorCall(maxCountExpression)
38+
.createConstructorCall(maxCountExpression, lockExpression)
3739
}
3840
field.initializer = irFactory.createExpressionBody(constructorCall)
3941
field.parent = function.parent

cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/factory/IrCacheableFunctionBodyFactory.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class IrCacheableFunctionBodyFactory(
154154
)
155155
}
156156
return if (isSuspend) {
157-
cacheableDeclarations.suspendCacheStoreClassDeclaration
157+
cacheableDeclarations.coroutineCacheStoreClassDeclaration
158158
.createCacheOrInvokeFunctionCall(
159159
typeArgument = typeArgument,
160160
keyElements = keyElements,

cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/Cacheable.kt

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ package com.moriatsushi.cacheable
88
*
99
* @param maxCount The maximum number of caches. If the number of caches exceeds this value, the
1010
* last used cache will be deleted. The default value is [unlimited][UNLIMITED_CACHE_COUNT].
11+
* @param lock When this is true, the function is guaranteed to be called only once even if the
12+
* function is called multiple times with the same arguments at the same time. Otherwise, the
13+
* function may be called multiple times with the same arguments at the same time. The default value
14+
* is false.
1115
*/
1216
@Target(AnnotationTarget.FUNCTION)
1317
@Retention(AnnotationRetention.SOURCE)
1418
@MustBeDocumented
15-
annotation class Cacheable(val maxCount: Int = UNLIMITED_CACHE_COUNT)
19+
annotation class Cacheable(
20+
val maxCount: Int = UNLIMITED_CACHE_COUNT,
21+
val lock: Boolean = false,
22+
)
1623

1724
/**
1825
* A constant indicating that the number of caches is unlimited.

cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/CacheStore.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ internal class CacheStore(
1212
private val lockStore: LockStore<SynchronizedObject> = LockStore.SynchronizedObjectStore,
1313
private val lock: Boolean = false,
1414
) {
15-
constructor(maxCount: Int = UNLIMITED_CACHE_COUNT) : this(BaseCacheStore(maxCount))
15+
constructor(
16+
maxCount: Int = UNLIMITED_CACHE_COUNT,
17+
lock: Boolean = false,
18+
) : this(BaseCacheStore(maxCount), lock = lock)
1619

1720
inline fun <T> cacheOrInvoke(vararg key: Any?, value: () -> T): T {
1821
val keyList = key.toList()

cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/CoroutineCacheStore.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ internal class CoroutineCacheStore(
1212
private val lockStore: LockStore<Mutex> = LockStore.MutexStore,
1313
private val lock: Boolean = false,
1414
) {
15-
constructor(maxCount: Int = UNLIMITED_CACHE_COUNT) : this(BaseCacheStore(maxCount))
15+
constructor(
16+
maxCount: Int = UNLIMITED_CACHE_COUNT,
17+
lock: Boolean = false,
18+
) : this(BaseCacheStore(maxCount), lock = lock)
1619

1720
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
1821
suspend inline fun <T> cacheOrInvoke(vararg key: Any?, value: suspend () -> T): T {

0 commit comments

Comments
 (0)