void c_ContinuationWaitHandle::Create(c_Continuation* continuation) { assert(continuation); assert(continuation->m_waitHandle.isNull()); AsioSession* session = AsioSession::Get(); uint16_t depth = session->getCurrentWaitHandleDepth(); if (UNLIKELY(depth >= MAX_DEPTH)) { Object e(SystemLib::AllocInvalidOperationExceptionObject( "Asio stack overflow")); throw e; } if (UNLIKELY(continuation->started())) { Object e(SystemLib::AllocInvalidOperationExceptionObject( continuation->running() ? "Encountered an attempt to start currently running continuation" : "Encountered an attempt to start tainted continuation")); throw e; } continuation->m_waitHandle = NEWOBJ(c_ContinuationWaitHandle)(); continuation->m_waitHandle->initialize(continuation, depth + 1); // needs to be called after continuation->m_waitHandle is set if (UNLIKELY(session->hasOnContinuationCreateCallback())) { session->onContinuationCreate(continuation->m_waitHandle.get()); } }
void c_AsyncFunctionWaitHandle::Create(c_Continuation* continuation) { assert(continuation); assert(continuation->m_label > 0); assert(continuation->m_waitHandle.isNull()); AsioSession* session = AsioSession::Get(); uint16_t depth = session->getCurrentWaitHandleDepth(); if (UNLIKELY(depth >= MAX_DEPTH)) { Object e(SystemLib::AllocInvalidOperationExceptionObject( "Asio stack overflow")); throw e; } Cell* value = tvAssertCell(continuation->m_value.asTypedValue()); assert(dynamic_cast<c_WaitableWaitHandle*>(c_WaitHandle::fromCell(value))); auto child = static_cast<c_WaitableWaitHandle*>(value->m_data.pobj); assert(!child->isFinished()); // import child into the current context, detect cross-context cycles if (session->isInContext()) { child->enterContext(session->getCurrentContextIdx()); } continuation->m_waitHandle = NEWOBJ(c_AsyncFunctionWaitHandle)(); continuation->m_waitHandle->initialize(continuation, child, depth + 1); // needs to be called after continuation->m_waitHandle is set if (UNLIKELY(session->hasOnAsyncFunctionCreateCallback())) { session->onAsyncFunctionCreate(continuation->m_waitHandle.get()); } }
Object c_ContinuationWaitHandle::ti_start(const char* cls, CObjRef continuation) { AsioSession* session = AsioSession::Get(); if (UNLIKELY(!continuation.instanceof(SystemLib::s_ContinuationClass))) { Object e(SystemLib::AllocInvalidArgumentExceptionObject( "Expected continuation to be an instance of Continuation")); throw e; } uint16_t depth = session->getCurrentWaitHandleDepth(); if (UNLIKELY(depth >= MAX_DEPTH)) { Object e(SystemLib::AllocInvalidOperationExceptionObject( "Asio stack overflow")); throw e; } c_Continuation* cont = static_cast<c_Continuation*>(continuation.get()); if (!cont->m_waitHandle.isNull()) { if (session->isInContext()) { // throws if cross-context cycle found cont->m_waitHandle->enterContext(session->getCurrentContextIdx()); } return cont->m_waitHandle; } if (UNLIKELY(cont->m_index != -1)) { assert(cont->m_running); Object e(SystemLib::AllocInvalidOperationExceptionObject( "Encountered an attempt to start currently running continuation")); throw e; } p_ContinuationWaitHandle wh = NEWOBJ(c_ContinuationWaitHandle)(); wh->start(cont, depth + 1); if (UNLIKELY(session->hasOnStartedCallback())) { session->onStarted(wh); } return wh; }