2 +----------------------------------------------------------------------+
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"
24 ///////////////////////////////////////////////////////////////////////////////
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"));
46 Object
c_RescheduleWaitHandle::ti_create(int queue
, int priority
) {
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"));
55 if (UNLIKELY(priority
< 0)) {
56 Object
e(SystemLib::AllocInvalidArgumentExceptionObject(
57 "Expected priority to be a non-negative integer"));
61 c_RescheduleWaitHandle
* wh
= NEWOBJ(c_RescheduleWaitHandle
);
62 wh
->initialize(static_cast<uint32_t>(queue
), static_cast<uint32_t>(priority
));
66 void c_RescheduleWaitHandle::initialize(uint32_t queue
, uint32_t priority
) {
68 m_priority
= priority
;
70 setState(STATE_SCHEDULED
);
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
) {
82 setResult(init_null_variant
.asTypedValue());
85 String
c_RescheduleWaitHandle::getName() {
89 void c_RescheduleWaitHandle::enterContext(context_idx_t ctx_idx
) {
90 assert(AsioSession::Get()->getContext(ctx_idx
));
92 // stop before corrupting unioned data
97 // already in the more specific context?
98 if (LIKELY(getContextIdx() >= ctx_idx
)) {
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
116 // not in a context being exited
117 assert(getContextIdx() <= ctx_idx
);
118 if (getContextIdx() != ctx_idx
) {
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
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 ///////////////////////////////////////////////////////////////////////////////