Skip to content
This repository was archived by the owner on Jul 13, 2020. It is now read-only.

addSingletonFactory may call its instantiation method multiple times #39

@inorichi

Description

@inorichi

Hello, I've been a long time user of this library and I liked it because of its simplicity. I know it's now deprecated in favor of the other Kotlin's DI libraries but I don't feel the need to change it and I've been hit by this bug I think it's worth mentioning.

This only happens when injecting the instance from multiple threads and the initialization takes some time.

Example demostrating the issue:

class A {
    init {
        Log.w("TAG", "Init A")
        Thread.sleep(1000) // Simulate slow init
    }
}

In your InjektModule class:

override fun InjektRegistrar.registerInjectables() {
    ...

    addSingletonFactory { A() } 
}

Then, to cause multiple instances (example using coroutines):

fun main(args: Array<String>) {
    repeat(5) {
        async { Injekt.get<A>() }
    }
}

One proposed solution is to change the addSingletonFactory implementation to a lazy so that synchronization is taken into account:

@Suppress("UNCHECKED_CAST")
override fun <R: Any> addSingletonFactory(forType: TypeReference<R>, factoryCalledOnce: () -> R) {
    factories.put(forType.type, {
        (existingValues.getOrPut(Instance(forType.type, NOKEY)) { lazy { factoryCalledOnce() } } as Lazy<R>).value
    })
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions