diff --git a/hphp/runtime/ext/asio/asio_external_thread_event.cpp b/hphp/runtime/ext/asio/asio_external_thread_event.cpp index 2d5f66121..ba9e76415 100644 --- a/hphp/runtime/ext/asio/asio_external_thread_event.cpp +++ b/hphp/runtime/ext/asio/asio_external_thread_event.cpp @@ -23,10 +23,10 @@ namespace HPHP { /////////////////////////////////////////////////////////////////////////////// -AsioExternalThreadEvent::AsioExternalThreadEvent() +AsioExternalThreadEvent::AsioExternalThreadEvent(ObjectData* priv_data) : m_session(AsioSession::Get()), m_state(Waiting) { - m_waitHandle = c_ExternalThreadEventWaitHandle::Create(this); + m_waitHandle = c_ExternalThreadEventWaitHandle::Create(this, priv_data); } void AsioExternalThreadEvent::abandon() { diff --git a/hphp/runtime/ext/asio/asio_external_thread_event.h b/hphp/runtime/ext/asio/asio_external_thread_event.h index aaa2aec76..dcbcd11cb 100644 --- a/hphp/runtime/ext/asio/asio_external_thread_event.h +++ b/hphp/runtime/ext/asio/asio_external_thread_event.h @@ -195,7 +195,15 @@ class AsioExternalThreadEvent { virtual void unserialize(TypedValue* result) const = 0; protected: - AsioExternalThreadEvent(); + /** + * Construct AsioExternalThreadEvent + * + * Subclass may optionally pass a PHP object (usually defined by extension) + * that can be accessed during unserialize() via getPrivData(). A reference + * to the object will be held while associated ExternalThreadEventWaitHandle + * object is in WAITING state. + */ + explicit AsioExternalThreadEvent(ObjectData* priv_data = nullptr); /** * Destruct AsioExternalThreadEvent @@ -222,6 +230,17 @@ class AsioExternalThreadEvent { */ void markAsFinished(); + /** + * Get private PHP data needed for unserialization. + * + * This function obtains private data stored by constructor. It may be + * called only from the unserialize() implementation. + */ + ObjectData* getPrivData() const { + assert(m_state.load() == Finished); + return m_waitHandle->getPrivData(); + } + private: enum state_t : uint32_t { /** diff --git a/hphp/runtime/ext/asio/external_thread_event_wait_handle.cpp b/hphp/runtime/ext/asio/external_thread_event_wait_handle.cpp index 8565bac09..ee97fbe80 100644 --- a/hphp/runtime/ext/asio/external_thread_event_wait_handle.cpp +++ b/hphp/runtime/ext/asio/external_thread_event_wait_handle.cpp @@ -62,16 +62,17 @@ void c_ExternalThreadEventWaitHandle::t___construct() { throw e; } -c_ExternalThreadEventWaitHandle* c_ExternalThreadEventWaitHandle::Create(AsioExternalThreadEvent* event) { +c_ExternalThreadEventWaitHandle* c_ExternalThreadEventWaitHandle::Create(AsioExternalThreadEvent* event, ObjectData* priv_data) { c_ExternalThreadEventWaitHandle* wh = NEWOBJ(c_ExternalThreadEventWaitHandle); - wh->initialize(event); + wh->initialize(event, priv_data); return wh; } -void c_ExternalThreadEventWaitHandle::initialize(AsioExternalThreadEvent* event) { +void c_ExternalThreadEventWaitHandle::initialize(AsioExternalThreadEvent* event, ObjectData* priv_data) { // this wait handle is owned by existence of unprocessed event incRefCount(); m_event = event; + m_privData = priv_data; setState(STATE_WAITING); if (isInContext()) { @@ -114,6 +115,7 @@ void c_ExternalThreadEventWaitHandle::process() { // event is processed, destroy it, unregister sweepable and decref ownership m_event->release(); m_event = nullptr; + m_privData = nullptr; unregister(); decRefObj(this); } diff --git a/hphp/runtime/ext/ext_asio.h b/hphp/runtime/ext/ext_asio.h index e2d70af3d..32dde17ea 100644 --- a/hphp/runtime/ext/ext_asio.h +++ b/hphp/runtime/ext/ext_asio.h @@ -439,10 +439,11 @@ class c_ExternalThreadEventWaitHandle : public c_WaitableWaitHandle, public Swee public: void t___construct(); public: - static c_ExternalThreadEventWaitHandle* Create(AsioExternalThreadEvent* event); + static c_ExternalThreadEventWaitHandle* Create(AsioExternalThreadEvent* event, ObjectData* priv_data); c_ExternalThreadEventWaitHandle* getNextToProcess() { assert(getState() == STATE_WAITING); return m_nextToProcess; } void setNextToProcess(c_ExternalThreadEventWaitHandle* next) { assert(getState() == STATE_WAITING); m_nextToProcess = next; } + ObjectData* getPrivData() { return m_privData.get(); } void setIndex(uint32_t ete_idx) { assert(getState() == STATE_WAITING); m_index = ete_idx; } void abandon(bool sweeping); @@ -452,10 +453,11 @@ class c_ExternalThreadEventWaitHandle : public c_WaitableWaitHandle, public Swee void exitContext(context_idx_t ctx_idx); private: - void initialize(AsioExternalThreadEvent* event); + void initialize(AsioExternalThreadEvent* event, ObjectData* priv_data); c_ExternalThreadEventWaitHandle* m_nextToProcess; AsioExternalThreadEvent* m_event; + Object m_privData; uint32_t m_index; static const uint8_t STATE_WAITING = 3;