Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coroutines under the hood #4

Open
daehwan2da opened this issue Mar 5, 2023 · 0 comments
Open

Coroutines under the hood #4

daehwan2da opened this issue Mar 5, 2023 · 0 comments

Comments

@daehwan2da
Copy link
Owner

daehwan2da commented Mar 5, 2023

coroutine 이 실제로 어떻게 동작되어지는가?

  • explain to a satisfactory level how coroutines work.

CPS

Continuation Passing Style

  • Continuation 을 Function2Function 으로 전달해간다.

suspend fun getUser(): User?

-> fun getUser(continuation: Continuation<*>) : Any?

suspend fun setUser(user: User)

-> fun setUser(user: User, continuation: Continuation<*>) : Any?

suspend fun checkAvailability(flight: Flight) : Boolean

-> fun checkAvailability(flight: Flight, continuation: Continuation<*>) : Any

suspend func 변환 후

// as-is
suspend fun myFunction() { 
  println("Before")
  delay(1000)
  println("After")
}

// to-be
fun myFunction(continuation: Continuation<*>) : Any {
  // continuation 을 해당 function 의 continuation 으로 생성 및 반환 해주는 전처리 작업이 추가된다.
  // MyFunctionContinuation 이라는 naming 이 되지는 않고, 이해를 돕기 쉬운 네이밍이다.
  val continuation = continuation as? MyFunctionContinuation ? MyFunctionContinuation(continuation)

  // label 에 맞춰서 suspend 전과 후 상태를 보장하고 처리를 분리한다.
  if (continuation.label == 0) {
    println("Before")
    continuation.label = 1
    if (delay(1000, continuation) == COROUTINE_SUSPENDED)
      return COROUTINE_SUSPENDED
  }
  
  if (continuation.label == 1) {
    println("After")
    return Unit
  }

  error("Imposible")
}

class MyFunctionContinuation( val completion : Continuation<Unit>) : Continuation<Unit> {
  override val context : CoroutineContext
    get() = completion.context

  // status 를 가진다.
  val label = 0
  var result : Result<Any> ?= null
  
  override fun resumeWith(result: Result<String>) {
    this.result = result
    val res = try {
      val r = myFunction(this)
      if ( r == COROUTINE_SUSPENDED) return Result.success(r as Unit)
    } catch (t : Throwable) {
      Result.failure(t)
    }
   completion.resumeWith(res)
  }
}

State machine

suspend 를 위해 각 function 들은 상태를 가지게 된다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant