Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 412 Vote(s) - 3.52 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Kotlin suspend fun

#1
I have Kotlin interface

interface FileSystem {
suspend fun getName(path: Path): List<String>
}

How I can call it from Java? What is

Continuation <? super List<String>>

[![enter image description here][1]][1]


[1]:
Reply

#2
Kotlin implements coroutines using a mix of the regular stack-based calling convention and the _continuation-passing style_ (CPS). To achieve that, it performs a _CPS transformation_ on all `suspend fun`s by adding an implicit parameter, an object you can use to continue the program from the place where the function was called. That's how Kotlin manages to pull off the trick to suspend the execution within your function's body: it extracts the continuation object, saves it somewhere, and then makes your function return (without yet having produced its value). Later on it can achieve the effect of jumping into the middle of your function body by invoking the continuation object.

The continuation is basically a callback object, just like those familiar from async Java APIs. Instead of returning its result, the suspendable function passes its result to the continuation. To call a `suspend fun` from java, you'll have to create such a callback. Here's an example:

Continuation<List<String>> myCont = new Continuation<List<String>>() {
@Override public void resume(List<String> result) {
System.out.println("Result of getName is " + result);
}
@Override public void resumeWithException(Throwable throwable) {
throwable.printStackTrace();
}
@NotNull @Override public CoroutineContext getContext() {
return Unconfined.INSTANCE;
}
};

> NOTE: The above works only with experimental coroutines. In the final API there's just one resumption method: `resumeWith(result: Result<T>)` where `Result` is a discriminated union of the result type and the `internal class Failure`, which makes it inaccessible from Java.

Let's also create a mock implementation of the `FileSystem` interface:

class MockFs : FileSystem {
override suspend fun getName(path: Path): List<String> {
suspendCoroutine<Unit> {
println("getName suspended")
}
println("getName resumed")
return listOf("usr", "opt")
}
}

Now we're ready to call it from Java:

Object result = new MockFs().getName(Paths.get(""), myCont);
System.out.println("getName returned " + result);

It prints

getName suspended
getName returned
kotlin.coroutines.experimental.intrinsics.CoroutineSuspendedMarker@6ce253f1

`getName()` returned a special marker object that signals the function got suspended. The function will pass its actual result to our callback, once it resumes.

Let us now improve `MockFs` so we can get access to the continuation:

class MockFs : FileSystem {
var continuation : Continuation<Unit>? = null

override suspend fun getName(path: Path): List<String> {
suspendCoroutine<Unit> {
continuation = it
println("getName suspended")
}
println("getName resumed")
return listOf("usr", "opt")
}
}

Now we'll be able to manually resume the continuation. We can use this code:

MockFs mockFs = new MockFs();
mockFs.getName(Paths.get(""), myCont);
mockFs.getContinuation().resume(Unit.INSTANCE);

This will print

getName suspended
getName resumed
Result of getName is [usr, opt]

In real life a suspendable function will use some mechanism to get itself resumed when the result becomes available. For example, if it's a wrapper around some async API call, it will register a callback. When the async API invokes the callback, it will in turn invoke our continuation. You shouldn't need to manually resume it like we did in our mock code.

A `suspend fun` also has the option to just return its result directly. For example, with this `MockFs` code

class MockFs : FileSystem {
override suspend fun getName(path: Path) = listOf("usr", "opt")
}

in Java we can just say

System.out.println(new MockFs().getName(Paths.get(""), myCont));

and it will print `[usr, opt]`. We could even have passed in an empty implementation of `Continuation`.

The most demanding case happens when you don't know in advance whether the function will suspend itself or not. In such a case a good approach is to write the following at the call site:

Object retVal = mockFs.getName(Paths.get(""), myCont);
if (retVal != IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
myCont.resume((List<String>) retVal);
}

Otherwise you'll have to duplicate the code that handles the function's result.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through