k
OK
a
well I have some diff in other stuff ...
then, I have at minimum 220 files diffs 😛
When I have high structural impact like that, I restart from the `koin-core`project and after that I reanble the others modules
merging with PR via Github won’t make it better I think
k
Are the diffs changes from after my branch?
a
I pushed your branch on the Koin repo
and try to merge to master (just for try)
k
Got it. might make sense if I take a look at that
a
yes, I will make a tour
I will have some questions for you ;)
k
I pulled master (from yesterday) into my branch and merged. I still need to review and move some things around, so it’s not done, but I’m working on it. Created a new offshoot branch in my repo. Will look at this more over the next couple days. https://github.com/kpgalligan/koin/tree/kpg/kmp_update
May make sense to resolve current diffs, then push an “experimental” multiplatform release, and target a big merge after 2.1.0
a
I will push a new Context Holder mechanism
k
OK
a
Will help us have a single thread context and a global static context
the first one, we would use ThreadLocal to store the context, I believe you’ve done like that in your branch
k
It’s not ThreadLocal per say. If you try to request from a background thread, it’ll go to the main thread to get the value.
a
ok, there is 2 things then - The Single Thread Context & helpers to go back to this thread if you need
k
Yeah, so the way I wrote it, if you just config Koin like normal without specifically allowing other thread access, and you try to inject from another thread, you’ll get an exception. You can configure components to be able to be accessed from a background thread. The idea is if you access a component from another thread, you have to freeze it, and I really want that to be an explicit choice. If you’re going to reimplement the context access, that’s something to keep in mind. The user should not be able to access something from another thread without somehow indicating that they’re aware they’re doing that. If we just auto-freeze, it’s not a great situation (in my opinion).
To be clear, though, you are making a new implementation? I was going to poke around doing the “all thread” version, but if you’re doing that I’ll hold off.
a
The user should not be able to access something from another thread without somehow indicating that they’re aware they’re doing that. If we just auto-freeze, it’s not a great situation (in my opinion).
sure
I’ll push my branch, I will show you what I’ve begin
from that point, we can setup any Kind of KoinContext
default is the Global one
what do you think about that?
k
I’ll need to get back to you. Meetings, also launching this today https://twitter.com/kpgalligan/status/1225471671248748551?s=20
Been super distracted
a
No problem 🙂
it’s already nice that we can chat and work about that 🙂
I will dig into your code and ask you other stuff ... answer me later 😉
k
Yeah, it would be great if we could sort out a test build around the time 1.3.70 goes out. Will definitely be putting some time into this
a
whoo yeah 🙂
I believe we can handle thread checking when we get the KoinContext (component that is holding the Koin instance)
this is the earliest point of access to Koin
and in a first approach, I see as: • can I access Koin in Static ? • can I access Koin in Thread Local ?
and then we get the right Koin instance and resolve it naturally, because we are on the right thrad or a static context
I’ve seen that you try to check that at several point (BeanDefinition, Koin.get ...)
I would be clearly optimis to try to place it at this first point
is the
MainIsolatedState
class a way to ensure stable reference in current thread?
I guess there is no ThreadLocal stuff in KotlinNative
k
Yeah. It’s all kind of in the following
Copy code
internal expect class MainIsolatedState<T:Any>(startVal: T) {
    fun _get(): T
}

internal inline val <T:Any> MainIsolatedState<T>.value: T
    get() {
        assertMainThread()
        return _get()
    }
When accessing the value with
.value
, it checks that you’re on the main thread. If so, it calls
_get()
. On JVM, you could just use synchronized to make sure you’re getting it “safely”, but on native, we actually need to make sure it’s on the right thread
Copy code
internal actual class MainIsolatedState<T:Any> actual constructor(startVal: T) {
    private val stableRef = StableRef.create(startVal)
    init {
        startVal.ensureNeverFrozen()
        freeze()
    }
    actual fun _get(): T = stableRef.get()
}
StableRef
essentially lets you get a pointer, and you can pass that pointer around, but when you call
stableRef.get()
, if you’re not on the thread that state belongs to, you have big problems.
Accessing that from calls that need to be on the main thread, you can just call
.value
, and there will be an exception if you’re not on the main thread. If the call should be able to be from another thread, there’s
mainOrBlock
, which will block the caller and go to the main thread for that state (if configured to allow that)
Without thinking about it too much, those mechanisms could have slightly different implementations. Instead of failing on some calls and switching threads on others, there could be a set of functions with lambdas
accessConfig {}
and
accessInvoke {}
. Something like that. In the main-thread instance,
accessConfig
would throw if not in main thread, and
accessInvoke
would block and move to main thread. In multi-thread,
accessConfig
and
accessInvoke
would just wrap calls in synchronized, although doing that just to inject could be problematic for performance.
Anyway, still have to look at your code. Busy couple days. This went out yesterday, actually using the Koin MP version I had in my branch. https://github.com/touchlab/KaMPKit
👍 1
a
make sense 👍
I will keep you touch
k
OK. Sounds good
Any updates over the weekend? Will take a look if things are stable-ish. Was thinking instead of configuring background thread access on setup we could have different inject methods
a
didn’t touch anything those days 😕
I still believe that we can tackle KMP when we get Koin context
this is the most simple case … I need to setup a CoffeeMakerAppMP to help me test the first things