#ifndef object_wrap_h #define object_wrap_h #include #include namespace node { class ObjectWrap { public: ObjectWrap ( ) { attached_ = 0; } virtual ~ObjectWrap ( ) { if (!handle_.IsEmpty()) { assert(handle_.IsNearDeath()); handle_->SetInternalField(0, v8::Undefined()); handle_.Dispose(); handle_.Clear(); } } protected: template static inline T* Unwrap (v8::Handle handle) { assert(!handle.IsEmpty()); assert(handle->InternalFieldCount() > 0); return static_cast(v8::Handle::Cast( handle->GetInternalField(0))->Value()); } inline void Wrap (v8::Handle handle) { assert(handle_.IsEmpty()); assert(handle->InternalFieldCount() > 0); handle_ = v8::Persistent::New(handle); handle_->SetInternalField(0, v8::External::New(this)); MakeWeak(); } inline void MakeWeak (void) { handle_.MakeWeak(this, WeakCallback); } /* Attach() marks the object as being attached to an event loop. * Attached objects will not be garbage collected, even if * all references are lost. */ virtual void Attach() { assert(!handle_.IsEmpty()); assert(handle_.IsWeak()); attached_++; } /* Detach() marks an object as detached from the event loop. This is its * default state. When an object with a "weak" reference changes from * attached to detached state it will be freed. Be careful not to access * the object after making this call as it might be gone! * (A "weak reference" is v8 terminology for an object that only has a * persistant handle.) * * DO NOT CALL THIS FROM DESTRUCTOR */ virtual void Detach() { assert(!handle_.IsEmpty()); assert(handle_.IsWeak()); assert(attached_ > 0); attached_--; if (attached_ == 0 && handle_.IsNearDeath()) delete this; } v8::Persistent handle_; // ro int attached_; // ro private: static void WeakCallback (v8::Persistent value, void *data) { ObjectWrap *obj = static_cast(data); assert(value == obj->handle_); if (obj->attached_ == 0) { delete obj; } else { obj->MakeWeak(); } } }; } // namespace node #endif // object_wrap_h