Skip to content

Commit 64a5992

Browse files
authored
Merge pull request #197 from Jeffset/thread-asserter-fix
[api] Re-implement thread assertions as an option instead of global state.
2 parents 502e772 + 46026c7 commit 64a5992

File tree

81 files changed

+489
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+489
-147
lines changed

api/dynamic/src/main/kotlin/com/yandex/yatagan/dynamic/ReflectionLoader.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ private const val MAX_ISSUE_ENCOUNTER_PATHS_PROPERTY = "maxIssueEncounterPaths"
3434
private const val IS_STRICT_MODE_PROPERTY = "enableStrictMode"
3535
private const val USE_PLAIN_OUTPUT_PROPERTY = "usePlainOutput"
3636
private const val DAGGER_COMPATIBILITY = "enableDaggerCompatibility"
37+
private const val THREAD_CHECKER_CLASS_NAME = "threadCheckerClassName"
3738

3839
/**
3940
* Instantiated reflectively.
@@ -91,6 +92,9 @@ internal class ReflectionLoader : ImplementationLoader by ReflectionLoader {
9192
params.enableDaggerCompatibility = value.toString().toBooleanStrictOrNull()
9293
?: throw IllegalStateException("Expected boolean for `$property`, got `$value`")
9394
}
95+
THREAD_CHECKER_CLASS_NAME -> {
96+
params.threadCheckerClassName = value?.toString()
97+
}
9498
else -> {
9599
throw IllegalStateException("Unknown property `$property`")
96100
}

api/public/api/public.api

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ public final class com/yandex/yatagan/Yatagan {
176176
public static final fun autoBuilder (Ljava/lang/Class;)Lcom/yandex/yatagan/AutoBuilder;
177177
public static final fun builder (Ljava/lang/Class;)Ljava/lang/Object;
178178
public static final fun create (Ljava/lang/Class;)Ljava/lang/Object;
179-
public static final fun getThreadAsserter ()Lcom/yandex/yatagan/ThreadAsserter;
180179
public static final fun setThreadAsserter (Lcom/yandex/yatagan/ThreadAsserter;)V
181180
}
182181

api/public/src/main/kotlin/com/yandex/yatagan/Yatagan.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ public object Yatagan {
4747
null
4848
}
4949

50-
/**
51-
* [ThreadAsserter] object to be used in Single Thread component implementations.
52-
*/
53-
@Volatile
5450
@JvmStatic
55-
public var threadAsserter: ThreadAsserter? = null
51+
@Deprecated(
52+
"Use `yatagan.threadCheckerClassName` option instead.",
53+
level = DeprecationLevel.ERROR,
54+
)
55+
@Suppress("UNUSED_PARAMETER")
56+
public fun setThreadAsserter(threadAsserter: ThreadAsserter?) {
57+
// NOP
58+
}
5659

5760
/**
5861
* Use this to create a component builder instance for root components that declare it.

api/public/src/main/kotlin/com/yandex/yatagan/internal/ThreadAssertions.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616

1717
package com.yandex.yatagan.internal
1818

19-
import com.yandex.yatagan.Yatagan
20-
19+
@Deprecated(
20+
message = "May be used by components generated with earlier versions of the framework",
21+
level = DeprecationLevel.HIDDEN,
22+
)
2123
@YataganInternal
2224
public object ThreadAssertions {
2325
@JvmStatic
2426
public fun assertThreadAccess() {
25-
// TODO(#44): Remove this and use `Yatagan.threadAsserter` directly.
26-
Yatagan.threadAsserter?.assertThreadAccess()
27+
// No-op
2728
}
2829
}

codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/ComponentGenerator.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.yandex.yatagan.codegen.poetry.TypeSpecBuilder
2424
import com.yandex.yatagan.codegen.poetry.buildClass
2525
import com.yandex.yatagan.codegen.poetry.buildExpression
2626
import com.yandex.yatagan.core.graph.BindingGraph
27+
import com.yandex.yatagan.core.graph.ThreadChecker
2728
import com.yandex.yatagan.core.graph.component1
2829
import com.yandex.yatagan.core.graph.component2
2930
import com.yandex.yatagan.lang.Field
@@ -39,6 +40,7 @@ import javax.lang.model.element.Modifier.STATIC
3940
@Singleton
4041
internal class ComponentGenerator @Inject constructor(
4142
component: GeneratorComponent,
43+
threadChecker: ThreadChecker,
4244
private val options: Options,
4345
private val graph: BindingGraph,
4446
private val contributors: List<Contributor>,
@@ -51,7 +53,6 @@ internal class ComponentGenerator @Inject constructor(
5153
data class Options(
5254
val maxSlotsPerSwitch: Int,
5355
val enableProvisionNullChecks: Boolean,
54-
val enableThreadChecks: Boolean,
5556
val sortMethodsForTesting: Boolean,
5657
val generatedAnnotationClassName: ClassName?,
5758
val enableDaggerCompatMode: Boolean,
@@ -65,6 +66,7 @@ internal class ComponentGenerator @Inject constructor(
6566
Yatagan.builder(GeneratorComponent.Factory::class.java).create(
6667
graph = childGraph,
6768
options = options,
69+
threadChecker = threadChecker,
6870
).generator
6971
}
7072

codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/ComponentGeneratorFacade.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ import com.squareup.javapoet.JavaFile
2121
import com.squareup.javapoet.TypeSpec
2222
import com.yandex.yatagan.Yatagan
2323
import com.yandex.yatagan.core.graph.BindingGraph
24+
import com.yandex.yatagan.core.graph.ThreadChecker
2425
import com.yandex.yatagan.lang.langFactory
2526

2627
class ComponentGeneratorFacade(
2728
graph: BindingGraph,
2829
maxSlotsPerSwitch: Int,
29-
enableThreadChecks: Boolean,
3030
enableProvisionNullChecks: Boolean,
3131
sortMethodsForTesting: Boolean,
3232
enableDaggerCompatMode: Boolean,
33+
threadChecker: ThreadChecker,
3334
) {
3435
interface GeneratedFile {
3536
val targetPackageName: String
@@ -43,11 +44,11 @@ class ComponentGeneratorFacade(
4344
options = ComponentGenerator.Options(
4445
maxSlotsPerSwitch = maxSlotsPerSwitch,
4546
enableProvisionNullChecks = enableProvisionNullChecks,
46-
enableThreadChecks = enableThreadChecks,
4747
sortMethodsForTesting = sortMethodsForTesting,
4848
generatedAnnotationClassName = generatedAnnotationClassName(),
4949
enableDaggerCompatMode = enableDaggerCompatMode,
5050
),
51+
threadChecker = threadChecker,
5152
)
5253

5354
fun generate(): List<GeneratedFile> = buildList {

codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/GeneratorComponent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.yandex.yatagan.Optional
1212
import com.yandex.yatagan.Provides
1313
import com.yandex.yatagan.base.api.Extensible
1414
import com.yandex.yatagan.core.graph.BindingGraph
15+
import com.yandex.yatagan.core.graph.ThreadChecker
1516
import javax.inject.Qualifier
1617
import javax.inject.Singleton
1718

@@ -61,6 +62,7 @@ internal interface GeneratorComponent {
6162
fun create(
6263
@BindsInstance graph: BindingGraph,
6364
@BindsInstance options: ComponentGenerator.Options,
65+
@BindsInstance threadChecker: ThreadChecker,
6466
): GeneratorComponent
6567
}
6668

codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/Names.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ internal object Names {
2424
val Provider: ClassName = ClassName.get("javax.inject", "Provider")
2525
val Optional: ClassName = ClassName.get("com.yandex.yatagan", "Optional")
2626
val AutoBuilder: ClassName = ClassName.get("com.yandex.yatagan", "AutoBuilder")
27-
val ThreadAssertions: ClassName = ClassName.get("com.yandex.yatagan.internal", "ThreadAssertions")
2827
val Checks: ClassName = ClassName.get("com.yandex.yatagan.internal", "Checks")
29-
val YataganGenerated = ClassName.get("com.yandex.yatagan.internal", "YataganGenerated")
28+
val YataganGenerated: ClassName = ClassName.get("com.yandex.yatagan.internal", "YataganGenerated")
3029

3130
val AssertionError: ClassName = ClassName.get(java.lang.AssertionError::class.java)
3231
val Class: ClassName = ClassName.get(java.lang.Class::class.java)

codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/ScopedProviderGenerator.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.squareup.javapoet.ClassName
2020
import com.yandex.yatagan.codegen.poetry.TypeSpecBuilder
2121
import com.yandex.yatagan.codegen.poetry.buildClass
2222
import com.yandex.yatagan.core.graph.BindingGraph
23+
import com.yandex.yatagan.core.graph.ThreadChecker
2324
import javax.inject.Inject
2425
import javax.inject.Singleton
2526
import javax.lang.model.element.Modifier.FINAL
@@ -32,6 +33,7 @@ import javax.lang.model.element.Modifier.VOLATILE
3233
internal class ScopedProviderGenerator @Inject constructor(
3334
private val componentImplName: ClassName,
3435
private val options: ComponentGenerator.Options,
36+
private val threadChecker: ThreadChecker,
3537
graph: BindingGraph,
3638
) : ComponentGenerator.Contributor {
3739
private var isUsed = false
@@ -79,9 +81,7 @@ internal class ScopedProviderGenerator @Inject constructor(
7981
}
8082
}
8183
} else {
82-
if (options.enableThreadChecks) {
83-
+"%T.assertThreadAccess()".formatCode(Names.ThreadAssertions)
84-
}
84+
threadChecker.generateThreadAssertion(this)
8585
+"local = mDelegate.%N(mIndex)".formatCode(SlotSwitchingGenerator.FactoryMethodName)
8686
+"mValue = local"
8787
}

codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/accessStrategies.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.yandex.yatagan.codegen.poetry.ExpressionBuilder
2323
import com.yandex.yatagan.codegen.poetry.TypeSpecBuilder
2424
import com.yandex.yatagan.codegen.poetry.buildExpression
2525
import com.yandex.yatagan.core.graph.BindingGraph
26+
import com.yandex.yatagan.core.graph.ThreadChecker
2627
import com.yandex.yatagan.core.graph.bindings.Binding
2728
import com.yandex.yatagan.core.model.ConditionScope
2829
import com.yandex.yatagan.core.model.DependencyKind
@@ -70,7 +71,7 @@ internal class CachingStrategySingleThread @AssistedInject constructor(
7071
@Assisted binding: Binding,
7172
@FieldsNamespace fieldsNs: Namespace,
7273
@MethodsNamespace methodsNs: Namespace,
73-
private val options: ComponentGenerator.Options,
74+
private val threadChecker: ThreadChecker,
7475
) : CachingStrategyBase(binding, fieldsNs, methodsNs) {
7576
override fun generateInComponent(builder: TypeSpecBuilder) = with(builder) {
7677
val targetType = binding.target.typeName()
@@ -82,9 +83,7 @@ internal class CachingStrategySingleThread @AssistedInject constructor(
8283
returnType(targetType)
8384
+"%T local = this.%N".formatCode(ClassName.OBJECT, instanceFieldName)
8485
controlFlow("if (local == null)") {
85-
if (options.enableThreadChecks) {
86-
+"%T.assertThreadAccess()".formatCode(Names.ThreadAssertions)
87-
}
86+
threadChecker.generateThreadAssertion(this)
8887
+buildExpression {
8988
+"local = "
9089
binding.generateCreation(builder = this, inside = binding.owner, isInsideInnerClass = false)

0 commit comments

Comments
 (0)