void c_ExternalThreadEventWaitHandle::process() { assert(getState() == STATE_WAITING); if (isInContext()) { unregisterFromContext(); } // clean up once event is processed auto exit_guard = folly::makeGuard([&] { destroyEvent(); }); Cell result; try { m_event->unserialize(result); } catch (const Object& exception) { assert(exception->instanceof(SystemLib::s_ExceptionClass)); auto parentChain = getParentChain(); setState(STATE_FAILED); tvWriteObject(exception.get(), &m_resultOrException); parentChain.unblock(); auto session = AsioSession::Get(); if (UNLIKELY(session->hasOnExternalThreadEventFail())) { session->onExternalThreadEventFail(this, exception); } return; } catch (...) { auto parentChain = getParentChain(); setState(STATE_FAILED); tvWriteObject(AsioSession::Get()->getAbruptInterruptException(), &m_resultOrException); parentChain.unblock(); throw; } assert(cellIsPlausible(result)); auto parentChain = getParentChain(); setState(STATE_SUCCEEDED); cellCopy(result, m_resultOrException); parentChain.unblock(); auto session = AsioSession::Get(); if (UNLIKELY(session->hasOnExternalThreadEventSuccess())) { session->onExternalThreadEventSuccess(this, tvAsCVarRef(&result)); } }
bool c_ExternalThreadEventWaitHandle::cancel(const Object& exception) { if (getState() != STATE_WAITING) { return false; // already finished } if (!m_event->cancel()) { return false; } // canceled; the processing thread will take care of cleanup if (isInContext()) { unregisterFromContext(); } // clean up once we finish canceling event auto exit_guard = folly::makeGuard([&] { // unregister Sweepable m_sweepable.unregister(); m_privData.reset(); // drop ownership by pending event (see initialize()) decRefObj(this); }); auto parentChain = getParentChain(); setState(STATE_FAILED); tvWriteObject(exception.get(), &m_resultOrException); parentChain.unblock(); auto session = AsioSession::Get(); if (UNLIKELY(session->hasOnExternalThreadEventFail())) { session->onExternalThreadEventFail(this, exception, 0); } return true; }
void c_ExternalThreadEventWaitHandle::process() { assertx(getState() == STATE_WAITING); if (isInContext()) { unregisterFromContext(); } // Store the finish time of the underlying IO operation // So we can pass it in the finish callbacks // clean up once event is processed auto exit_guard = folly::makeGuard([&] { destroyEvent(); }); Cell result; try { try { m_event->unserialize(result); } catch (ExtendedException& exception) { exception.recomputeBacktraceFromWH(this); throw exception; } } catch (const Object& exception) { assertx(exception->instanceof(SystemLib::s_ThrowableClass)); throwable_recompute_backtrace_from_wh(exception.get(), this); auto parentChain = getParentChain(); setState(STATE_FAILED); tvWriteObject(exception.get(), &m_resultOrException); parentChain.unblock(); auto session = AsioSession::Get(); if (UNLIKELY(session->hasOnExternalThreadEventFail())) { session->onExternalThreadEventFail( this, exception, std::chrono::duration_cast<std::chrono::nanoseconds>( m_event->getFinishTime().time_since_epoch() ).count() ); } return; } catch (...) { auto parentChain = getParentChain(); setState(STATE_FAILED); tvWriteObject(AsioSession::Get()->getAbruptInterruptException(), &m_resultOrException); parentChain.unblock(); throw; } assertx(cellIsPlausible(result)); auto parentChain = getParentChain(); setState(STATE_SUCCEEDED); cellCopy(result, m_resultOrException); parentChain.unblock(); auto session = AsioSession::Get(); if (UNLIKELY(session->hasOnExternalThreadEventSuccess())) { session->onExternalThreadEventSuccess( this, tvAsCVarRef(&result), std::chrono::duration_cast<std::chrono::nanoseconds>( m_event->getFinishTime().time_since_epoch() ).count() ); } }