Skip to content

Commit

Permalink
Memoizing traversal over linked scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
octa-one committed Jan 19, 2022
1 parent 5b948ab commit 29182f3
Showing 1 changed file with 43 additions and 12 deletions.
55 changes: 43 additions & 12 deletions core/koin-core/src/commonMain/kotlin/org/koin/core/scope/Scope.kt
Expand Up @@ -167,9 +167,16 @@ data class Scope(
clazz: KClass<*>,
qualifier: Qualifier? = null,
parameters: ParametersDefinition? = null
): T? = getOrNull(clazz, qualifier, parameters, mutableSetOf())

private fun <T> getOrNull(
clazz: KClass<*>,
qualifier: Qualifier?,
parameters: ParametersDefinition?,
visitedScopes: MutableSet<Qualifier>
): T? {
return try {
get(clazz, qualifier, parameters)
get(clazz, qualifier, parameters, visitedScopes)
} catch (e: ClosedScopeException) {
_koin.logger.debug("|- Scope closed - no instance found for ${clazz.getFullName()} on scope ${toString()}")
null
Expand All @@ -191,17 +198,24 @@ data class Scope(
clazz: KClass<*>,
qualifier: Qualifier? = null,
parameters: ParametersDefinition? = null
): T = get(clazz, qualifier, parameters, mutableSetOf())

private fun <T> get(
clazz: KClass<*>,
qualifier: Qualifier?,
parameters: ParametersDefinition?,
visitedScopes: MutableSet<Qualifier>
): T {
return if (_koin.logger.isAt(Level.DEBUG)) {
val qualifierString = qualifier?.let { " with qualifier '$qualifier'" } ?: ""
_koin.logger.debug("+- '${clazz.getFullName()}'$qualifierString")
val (instance: T, duration: Double) = measureDurationForResult {
resolveInstance<T>(qualifier, clazz, parameters)
resolveInstance<T>(qualifier, clazz, parameters, visitedScopes)
}
_koin.logger.debug("|- '${clazz.getFullName()}' in $duration ms")
return instance
} else {
resolveInstance(qualifier, clazz, parameters)
resolveInstance(qualifier, clazz, parameters, visitedScopes)
}
}

Expand All @@ -227,7 +241,8 @@ data class Scope(
private fun <T> resolveInstance(
qualifier: Qualifier?,
clazz: KClass<*>,
parameterDef: ParametersDefinition?
parameterDef: ParametersDefinition?,
visitedScopes: MutableSet<Qualifier>
): T {
if (_closed) {
throw ClosedScopeException("Scope '$id' is closed")
Expand All @@ -238,7 +253,7 @@ data class Scope(
_parameterStack.addFirst(parameters)
}
val instanceContext = InstanceContext(_koin, this, parameters)
val value = resolveValue<T>(qualifier, clazz, instanceContext, parameterDef)
val value = resolveValue<T>(qualifier, clazz, instanceContext, parameterDef, visitedScopes)
if (parameters != null) {
_koin.logger.log(Level.DEBUG) { "| remove parameters from stack" }
_parameterStack.removeFirstOrNull()
Expand All @@ -250,11 +265,14 @@ data class Scope(
qualifier: Qualifier?,
clazz: KClass<*>,
instanceContext: InstanceContext,
parameterDef: ParametersDefinition?
parameterDef: ParametersDefinition?,
visitedScopes: MutableSet<Qualifier>
) = (_koin.instanceRegistry.resolveInstance(qualifier, clazz, this.scopeQualifier, instanceContext)
?: run {
_koin.logger.log(Level.DEBUG) { "- lookup? t:'${clazz.getFullName()}' - q:'$qualifier' look in injected parameters" }
_parameterStack.firstOrNull()?.getOrNull<T>(clazz)
if (visitedScopes.isEmpty()) {
_koin.logger.log(Level.DEBUG) { "- lookup? t:'${clazz.getFullName()}' - q:'$qualifier' look in injected parameters" }
_parameterStack.firstOrNull()?.getOrNull<T>(clazz)
} else null
}
?: run {
_koin.logger.log(Level.DEBUG) { "- lookup? t:'${clazz.getFullName()}' - q:'$qualifier' look at scope source" }
Expand All @@ -266,7 +284,7 @@ data class Scope(
}
?: run {
_koin.logger.log(Level.DEBUG) { "- lookup? t:'${clazz.getFullName()}' - q:'$qualifier' look in other scopes" }
findInOtherScope<T>(clazz, qualifier, parameterDef)
findInOtherScope<T>(clazz, qualifier, parameterDef, visitedScopes)
}
?: run {
_parameterStack.clear()
Expand All @@ -282,14 +300,17 @@ data class Scope(
private fun <T> findInOtherScope(
clazz: KClass<*>,
qualifier: Qualifier?,
parameters: ParametersDefinition?
parameters: ParametersDefinition?,
visitedScopes: MutableSet<Qualifier>
): T? {
var instance: T? = null
for (scope in linkedScopes) {
if (!visitedScopes.add(scope.scopeQualifier)) continue
instance = scope.getOrNull<T>(
clazz,
qualifier,
parameters
parameters,
visitedScopes
)
if (instance != null) break
}
Expand Down Expand Up @@ -357,8 +378,18 @@ data class Scope(
* @return list of instances of type T
*/
fun <T> getAll(clazz: KClass<*>): List<T> {
val accumulator = mutableListOf<T>()
getAll(clazz, accumulator, mutableSetOf())
return accumulator.toList()
}

private fun <T> getAll(clazz: KClass<*>, accumulator: MutableList<T>, visitedScopes: MutableSet<Qualifier>) {
val context = InstanceContext(_koin, this)
return _koin.instanceRegistry.getAll<T>(clazz, context) + linkedScopes.flatMap { scope -> scope.getAll(clazz) }
accumulator.addAll(_koin.instanceRegistry.getAll(clazz, context))
for (scope in linkedScopes) {
if (!visitedScopes.add(scope.scopeQualifier)) continue
scope.getAll(clazz, accumulator, visitedScopes)
}
}

// /**
Expand Down

0 comments on commit 29182f3

Please sign in to comment.