Has anyone here found a good way to integrate a ca...
# kotlin-native
s
Has anyone here found a good way to integrate a callback mechanism with the Workers API to do background execution? I want to kick off a background task and have it call a callback later without blocking, but that doesn’t seem to be possible if the callback mutates any state/references unfrozen objects. This seems like a fairly straightforward task but AFAIK there is currently no way to do it. I can do something like:
Copy code
val input = ...
val callback: (Result) -> Void = ...
val future = Worker.start().execute(TransferMode.SAFE, { input.freeze() }) {
    // do work
    result    
}
val result = future.result
callback(result)
But obviously that blocks the calling thread until execution is finished. Open to other suggestions besides
Worker
but I am not aware of any other mechanism for multithreading since coroutines only run on main thread.
l
j
future.consume { callback(it) }
a
This is conceptually impossible at the moment. Objects must belong to a single thread or be frozen. But it is possible to switch from a background thread back to the main thread and update the shared mutable state with the result.
o
It is not impossible, just to be properly arranged.
☝️ 1
a
@olonho How is it possible to share mutable state between threads with the current memory model? Without ownership transferring and freezing. Are there any examples? The only possible way I see is to use UNSAFE transfer and synchronize it with mutex, but it will randomly crash with segmentation fault errors.
o
It is not what TS asks for. He needs a callback executed after job is done.
a
TS wants to mutate a state in this callback, isn't it?
o
Callback can be executed on any thread, as long as it executes when computation is finished, if I understand the question correctly. You seem to misunderstand the computational model behind K/N, it isn’t evil set of rules to make programmers suffer, it is more like formalizing actual existing conventions and making them more strictly expressed in the execution runtime. Same is true with the continuation execution.
a
Sorry, me or TS? Let's be precise. TS asked: "I want to kick off a background task and have it call a callback later without blocking, but that doesn’t seem to be possible if the callback mutates any state/references unfrozen objects.". I responded with the message that it is conceptually impossible to mutate a state from a background callback without ownership transfer.
o
You. My point was that TS want to execute code after computation is done, but execution doesn’t have to happen in certain thread. In FP languages, like Kotlin, computation can be expressed as relatively disjoint entity, and thus, be executed in suitable context.
a
But I believe you got the question wrong, the main point of the question is to mutate a shared state inside this callback with a result of the computation. Not just execute some code after computation is done.
o
Guess you presumed state sharing, while it was neither mentioned nor needed. Unfortunately, it is indeed hard to explain part of K/N concurrency, that ownership or sharing is explicit part of contract of execution process. This could be achieved with existing K/N mechanisms, although sometimes it’s not very natural to express.
a
I think in this situation better to wait for TS, as I'm pretty sure he wants to execute a callback with the result of background computation and apply this result to a shared state (mutate it). Because I clearly see the following text in the original message/question: "but that doesn’t seem to be possible if the callback mutates any state/references unfrozen objects.".
s
Yes, essentially what I wanted to do was:
Copy code
val callback = { ... } // lambda that mutates global state 
val job = { ... } // lambda that is self contained/frozen (detached object graph)
val future = worker.execute(TransferMode.SAFE, { job }) { it() }

// this does not work as it blocks calling thread
future.consume { callback(it) }

// instead I want current thread/context to continue running 
// and have callback called once job is complete... however
// seems impossible since I can't pass callback to job as it mutates global state
All I want was to be able to execute a job asynchronously and call a callback upon completion. Meaning the thread calling
execute
does not block waiting on the completion.
So yes @Arkadii Ivanov I believe you understand most of what I asked, but I’d emphasize I want the callback to execute later without blocking to wait for it
Also wondering what TS stands for, is it similar to OP?