Something that came up yesterday when I was workin...
# coroutines
s
Something that came up yesterday when I was working with coroutines and thread locals: is there a way to use an inline higher-order function, but prevent its lambda parameter from suspending? Hypothetically something like:
Copy code
inline fun <T> foo(f: nosuspend () -> T): T
The use case is something like this:
Copy code
val threadLocal = ThreadLocal<String>()

inline fun <T> withFoo(f: () -> T):T  = try {
    threadLocal.set("foo")
    f()
} finally {
    threadLocal.remove()
}

suspend fun bar() {}

suspend fun main() {
    withFoo { bar() } // I want this to be an error
}
I don’t want to be able to call
bar()
inside
withFoo
, because it would be an error to set a thread local and then suspend
I know I can make a coroutine context element to get thread-local-like behaviour in a coroutine. And I know I can prevent the lambda parameter from suspending by making it not be inlined.
Thing is, the version of
withFoo
that I shared above is what I would write if coroutines didn’t exist. I want to be able to do that but ensure that nobody accidentally calls it with a suspending lambda. It’s as if the existence of coroutines is making my function signature unsafe 😕
e
s
Thanks @ephemient 🙇 I feel validated knowing that a ticket exists 😄
f
Unless you care about non-local returns, using the crossinline modifier on your lambda param is a decent workaround
l
@ephemient @Sam As just told in the comment above, there is actually a way: the
crossinline
modifier.
e
that makes the function as useful as a non-inline fun
l
Not exactly, you still get no allocation for the function parameters.