Throw an exception, not a pointer to one
[hiphop-php.git] / hphp / runtime / ext / asio / reschedule_wait_handle.cpp
blobb13ac824d6f0360ab8998460bfc9b451f0f46633
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #include "hphp/runtime/ext/ext_asio.h"
19 #include "hphp/runtime/ext/asio/asio_context.h"
20 #include "hphp/runtime/ext/asio/asio_session.h"
21 #include "hphp/system/systemlib.h"
23 namespace HPHP {
24 ///////////////////////////////////////////////////////////////////////////////
26 namespace {
27 StaticString s_reschedule("<reschedule>");
30 const int q_RescheduleWaitHandle$$QUEUE_DEFAULT = AsioContext::QUEUE_DEFAULT;
31 const int q_RescheduleWaitHandle$$QUEUE_NO_PENDING_IO = AsioContext::QUEUE_NO_PENDING_IO;
33 c_RescheduleWaitHandle::c_RescheduleWaitHandle(Class *cb)
34 : c_WaitableWaitHandle(cb) {
37 c_RescheduleWaitHandle::~c_RescheduleWaitHandle() {
40 void c_RescheduleWaitHandle::t___construct() {
41 Object e(SystemLib::AllocInvalidOperationExceptionObject(
42 "Use RescheduleWaitHandle::create() instead of constructor"));
43 throw e;
46 Object c_RescheduleWaitHandle::ti_create(int queue, int priority) {
47 if (UNLIKELY(
48 queue != q_RescheduleWaitHandle$$QUEUE_DEFAULT &&
49 queue != q_RescheduleWaitHandle$$QUEUE_NO_PENDING_IO)) {
50 Object e(SystemLib::AllocInvalidArgumentExceptionObject(
51 "Expected queue to be a value defined by one of the QUEUE_ constants"));
52 throw e;
55 if (UNLIKELY(priority < 0)) {
56 Object e(SystemLib::AllocInvalidArgumentExceptionObject(
57 "Expected priority to be a non-negative integer"));
58 throw e;
61 c_RescheduleWaitHandle* wh = NEWOBJ(c_RescheduleWaitHandle);
62 wh->initialize(static_cast<uint32_t>(queue), static_cast<uint32_t>(priority));
63 return wh;
66 void c_RescheduleWaitHandle::initialize(uint32_t queue, uint32_t priority) {
67 m_queue = queue;
68 m_priority = priority;
70 setState(STATE_SCHEDULED);
71 if (isInContext()) {
72 getContext()->schedule(this, m_queue, m_priority);
76 void c_RescheduleWaitHandle::run() {
77 // may happen if scheduled in multiple contexts
78 if (getState() != STATE_SCHEDULED) {
79 return;
82 setResult(init_null_variant.asTypedValue());
85 String c_RescheduleWaitHandle::getName() {
86 return s_reschedule;
89 void c_RescheduleWaitHandle::enterContext(context_idx_t ctx_idx) {
90 assert(AsioSession::Get()->getContext(ctx_idx));
92 // stop before corrupting unioned data
93 if (isFinished()) {
94 return;
97 // already in the more specific context?
98 if (LIKELY(getContextIdx() >= ctx_idx)) {
99 return;
102 assert(getState() == STATE_SCHEDULED);
104 setContextIdx(ctx_idx);
105 getContext()->schedule(this, m_queue, m_priority);
108 void c_RescheduleWaitHandle::exitContext(context_idx_t ctx_idx) {
109 assert(AsioSession::Get()->getContext(ctx_idx));
111 // stop before corrupting unioned data
112 if (isFinished()) {
113 return;
116 // not in a context being exited
117 assert(getContextIdx() <= ctx_idx);
118 if (getContextIdx() != ctx_idx) {
119 return;
122 if (UNLIKELY(getState() != STATE_SCHEDULED)) {
123 throw FatalErrorException(
124 "Invariant violation: encountered unexpected state");
127 // move us to the parent context
128 setContextIdx(getContextIdx() - 1);
130 // reschedule if still in a context
131 if (isInContext()) {
132 getContext()->schedule(this, m_queue, m_priority);
135 // recursively move all wait handles blocked by us
136 for (auto pwh = getFirstParent(); pwh; pwh = pwh->getNextParent()) {
137 pwh->exitContextBlocked(ctx_idx);
141 ///////////////////////////////////////////////////////////////////////////////