Provide safe storage for private PHP data in external thread events

Sometimes, a PHP object (usually defined by extension) is needed to
unserialize the data.

Provide a safe mechanism to store such object with external thread
events.
Esse commit está contido em:
Jan Oravec
2013-05-07 12:24:13 -07:00
commit de Sara Golemon
commit f2cf5fbaac
4 arquivos alterados com 31 adições e 8 exclusões
@@ -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() {
@@ -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 {
/**
@@ -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);
}
+4 -2
Ver Arquivo
@@ -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;