Arquivos
hhvm/hphp/runtime/ext/asio/reschedule_wait_handle.cpp
T
Paul Tarjan fef62f03a2 kill VM namespace
Now that HHVM is the default runtime, this namespace doesn't mean anything.
2013-05-15 13:05:05 -07:00

143 linhas
4.3 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <runtime/ext/ext_asio.h>
#include <runtime/ext/asio/asio_context.h>
#include <runtime/ext/asio/asio_session.h>
#include <system/lib/systemlib.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
namespace {
StaticString s_reschedule("<reschedule>");
}
const int q_RescheduleWaitHandle$$QUEUE_DEFAULT = AsioContext::QUEUE_DEFAULT;
const int q_RescheduleWaitHandle$$QUEUE_NO_PENDING_IO = AsioContext::QUEUE_NO_PENDING_IO;
c_RescheduleWaitHandle::c_RescheduleWaitHandle(Class *cb)
: c_WaitableWaitHandle(cb) {
}
c_RescheduleWaitHandle::~c_RescheduleWaitHandle() {
}
void c_RescheduleWaitHandle::t___construct() {
Object e(SystemLib::AllocInvalidOperationExceptionObject(
"Use RescheduleWaitHandle::create() instead of constructor"));
throw e;
}
Object c_RescheduleWaitHandle::ti_create(int queue, int priority) {
if (UNLIKELY(
queue != q_RescheduleWaitHandle$$QUEUE_DEFAULT &&
queue != q_RescheduleWaitHandle$$QUEUE_NO_PENDING_IO)) {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Expected queue to be a value defined by one of the QUEUE_ constants"));
throw e;
}
if (UNLIKELY(priority < 0)) {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Expected priority to be a non-negative integer"));
throw e;
}
c_RescheduleWaitHandle* wh = NEWOBJ(c_RescheduleWaitHandle);
wh->initialize(static_cast<uint32_t>(queue), static_cast<uint32_t>(priority));
return wh;
}
void c_RescheduleWaitHandle::initialize(uint32_t queue, uint32_t priority) {
m_queue = queue;
m_priority = priority;
setState(STATE_SCHEDULED);
if (isInContext()) {
getContext()->schedule(this, m_queue, m_priority);
}
}
void c_RescheduleWaitHandle::run() {
// may happen if scheduled in multiple contexts
if (getState() != STATE_SCHEDULED) {
return;
}
setResult(init_null_variant.asTypedValue());
}
String c_RescheduleWaitHandle::getName() {
return s_reschedule;
}
void c_RescheduleWaitHandle::enterContext(context_idx_t ctx_idx) {
assert(AsioSession::Get()->getContext(ctx_idx));
// stop before corrupting unioned data
if (isFinished()) {
return;
}
// already in the more specific context?
if (LIKELY(getContextIdx() >= ctx_idx)) {
return;
}
assert(getState() == STATE_SCHEDULED);
setContextIdx(ctx_idx);
getContext()->schedule(this, m_queue, m_priority);
}
void c_RescheduleWaitHandle::exitContext(context_idx_t ctx_idx) {
assert(AsioSession::Get()->getContext(ctx_idx));
// stop before corrupting unioned data
if (isFinished()) {
return;
}
// not in a context being exited
assert(getContextIdx() <= ctx_idx);
if (getContextIdx() != ctx_idx) {
return;
}
if (UNLIKELY(getState() != STATE_SCHEDULED)) {
throw new FatalErrorException(
"Invariant violation: encountered unexpected state");
}
// move us to the parent context
setContextIdx(getContextIdx() - 1);
// reschedule if still in a context
if (isInContext()) {
getContext()->schedule(this, m_queue, m_priority);
}
// recursively move all wait handles blocked by us
for (auto pwh = getFirstParent(); pwh; pwh = pwh->getNextParent()) {
pwh->exitContextBlocked(ctx_idx);
}
}
///////////////////////////////////////////////////////////////////////////////
}