/* -*- C++ -*- */ // $Id$ // Bound_Ptr.i #include "ace/Guard_T.h" #if !defined (ACE_NEW_THROWS_EXCEPTIONS) # include "ace/Log_Msg.h" #endif /* ACE_NEW_THROWS_EXCEPTIONS */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL template inline ACE_Bound_Ptr_Counter * ACE_Bound_Ptr_Counter::internal_create (int init_obj_ref_count) { ACE_Bound_Ptr_Counter *temp = 0; ACE_NEW_RETURN (temp, ACE_Bound_Ptr_Counter (init_obj_ref_count), 0); return temp; } template inline ACE_Bound_Ptr_Counter * ACE_Bound_Ptr_Counter::create_strong (void) { // Set initial object reference count to 1. ACE_Bound_Ptr_Counter *temp = internal_create (1); #if defined (ACE_NEW_THROWS_EXCEPTIONS) if (temp == 0) ACE_throw_bad_alloc; #else ACE_ASSERT (temp != 0); #endif /* ACE_NEW_THROWS_EXCEPTIONS */ return temp; } template inline int ACE_Bound_Ptr_Counter::attach_strong (ACE_Bound_Ptr_Counter* counter) { ACE_GUARD_RETURN (ACE_LOCK, guard, counter->lock_, -1); // Can't attach a strong pointer to an object that has already been deleted. if (counter->obj_ref_count_ == -1) return -1; int new_obj_ref_count = ++counter->obj_ref_count_; ++counter->self_ref_count_; return new_obj_ref_count; } template inline int ACE_Bound_Ptr_Counter::detach_strong (ACE_Bound_Ptr_Counter* counter) { ACE_Bound_Ptr_Counter *counter_del = 0; int new_obj_ref_count; { ACE_GUARD_RETURN (ACE_LOCK, guard, counter->lock_, -1); if ((new_obj_ref_count = --counter->obj_ref_count_) == 0) // Change the object reference count to -1 to indicate that the // object has been deleted, as opposed to a weak pointer that // simply hasn't had any strong pointers created from it yet. counter->obj_ref_count_ = -1; if (--counter->self_ref_count_ == 0) // Since counter contains the lock held by the ACE_Guard, the // guard needs to be released before freeing the memory holding // the lock. So save the pointer to free, then release, then // free. counter_del = counter; } // Release the lock delete counter_del; return new_obj_ref_count; } template inline ACE_Bound_Ptr_Counter * ACE_Bound_Ptr_Counter::create_weak (void) { // Set initial object reference count to 0. ACE_Bound_Ptr_Counter *temp = internal_create (0); #if defined (ACE_NEW_THROWS_EXCEPTIONS) if (temp == 0) ACE_throw_bad_alloc; #else ACE_ASSERT (temp != 0); #endif /* ACE_NEW_THROWS_EXCEPTIONS */ return temp; } template inline void ACE_Bound_Ptr_Counter::attach_weak (ACE_Bound_Ptr_Counter* counter) { ACE_GUARD (ACE_LOCK, guard, counter->lock_); ++counter->self_ref_count_; } template inline void ACE_Bound_Ptr_Counter::detach_weak (ACE_Bound_Ptr_Counter* counter) { ACE_Bound_Ptr_Counter *counter_del = 0; { ACE_GUARD (ACE_LOCK, guard, counter->lock_); if (--counter->self_ref_count_ == 0) // Since counter contains the lock held by the ACE_Guard, the // guard needs to be released before freeing the memory holding // the lock. So save the pointer to free, then release, then // free. counter_del = counter; } // Release the lock delete counter_del; } template inline int ACE_Bound_Ptr_Counter::object_was_deleted (ACE_Bound_Ptr_Counter *counter) { ACE_GUARD_RETURN (ACE_LOCK, guard, counter->lock_, 0); return counter->obj_ref_count_ == -1; } template inline ACE_Bound_Ptr_Counter::ACE_Bound_Ptr_Counter (int init_obj_ref_count) : obj_ref_count_ (init_obj_ref_count), self_ref_count_ (1) { } template inline ACE_Bound_Ptr_Counter::~ACE_Bound_Ptr_Counter (void) { } template inline ACE_Strong_Bound_Ptr::ACE_Strong_Bound_Ptr (X *p) : counter_ (COUNTER::create_strong ()), ptr_ (p) { } template inline ACE_Strong_Bound_Ptr::ACE_Strong_Bound_Ptr (auto_ptr p) : counter_ (COUNTER::create_strong ()), ptr_ (p.release()) { } template inline ACE_Strong_Bound_Ptr::ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr &r) : counter_ (r.counter_), ptr_ (r.ptr_) { COUNTER::attach_strong (this->counter_); } template inline ACE_Strong_Bound_Ptr::ACE_Strong_Bound_Ptr (const ACE_Weak_Bound_Ptr &r) : counter_ (r.counter_), ptr_ (r.ptr_) { // When creating a strong pointer from a weak one we can't assume that the // underlying object still exists. Therefore we must check for a return value // of -1, which indicates that the object has been destroyed. if (COUNTER::attach_strong (this->counter_) == -1) { // Underlying object has already been deleted, so set this pointer to null. this->counter_ = COUNTER::create_strong (); this->ptr_ = 0; } } template inline ACE_Strong_Bound_Ptr::~ACE_Strong_Bound_Ptr (void) { if (COUNTER::detach_strong (this->counter_) == 0) delete this->ptr_; } template inline void ACE_Strong_Bound_Ptr::operator = (const ACE_Strong_Bound_Ptr &rhs) { // This will work if &r == this, by first increasing the ref count COUNTER *new_counter = rhs.counter_; X_t *new_ptr = rhs.ptr_; COUNTER::attach_strong (new_counter); if (COUNTER::detach_strong (this->counter_) == 0) delete this->ptr_; this->counter_ = new_counter; this->ptr_ = new_ptr; } template inline void ACE_Strong_Bound_Ptr::operator = (const ACE_Weak_Bound_Ptr &rhs) { // This will work if &r == this, by first increasing the ref count COUNTER *new_counter = rhs.counter_; X_t *new_ptr = rhs.ptr_; // When creating a strong pointer from a weak one we can't assume that the // underlying object still exists. Therefore we must check for a return value // of -1, which indicates that the object has been destroyed. if (COUNTER::attach_strong (new_counter) == -1) { // Underlying object has already been deleted, so set this pointer to null. new_counter = COUNTER::create_strong (); new_ptr = 0; } if (COUNTER::detach_strong (this->counter_) == 0) delete this->ptr_; this->counter_ = new_counter; this->ptr_ = new_ptr; } template inline bool ACE_Strong_Bound_Ptr::operator== (const ACE_Strong_Bound_Ptr &r) const { return this->ptr_ == r.ptr_; } template inline bool ACE_Strong_Bound_Ptr::operator== (const ACE_Weak_Bound_Ptr &r) const { // Use the weak pointer's operator== since it will check for null. return r == *this; } template inline bool ACE_Strong_Bound_Ptr::operator== (X *p) const { return this->ptr_ == p; } template inline bool ACE_Strong_Bound_Ptr::operator!= (const ACE_Strong_Bound_Ptr &r) const { return this->ptr_ != r.ptr_; } template inline bool ACE_Strong_Bound_Ptr::operator!= (const ACE_Weak_Bound_Ptr &r) const { // Use the weak pointer's operator!= since it will check for null. return r != *this; } template inline bool ACE_Strong_Bound_Ptr::operator!= (X *p) const { return this->ptr_ != p; } template inline X * ACE_Strong_Bound_Ptr::operator-> (void) const { return this->ptr_; } template inline X & ACE_Strong_Bound_Ptr::operator *() const { return *this->ptr_; } template inline X* ACE_Strong_Bound_Ptr::get (void) const { return this->ptr_; } template inline int ACE_Strong_Bound_Ptr::null (void) const { return this->ptr_ == 0; } template inline void ACE_Strong_Bound_Ptr::reset (X *p) { COUNTER *old_counter = this->counter_; X_t *old_ptr = this->ptr_; this->counter_ = COUNTER::create_strong (); this->ptr_ = p; if (COUNTER::detach_strong (old_counter) == 0) delete old_ptr; } template inline void ACE_Strong_Bound_Ptr::reset (auto_ptr p) { COUNTER *old_counter = this->counter_; X_t *old_ptr = this->ptr_; this->counter_ = COUNTER::create_strong (); this->ptr_ = p.release (); if (COUNTER::detach_strong (old_counter) == 0) delete old_ptr; } template inline ACE_Weak_Bound_Ptr::ACE_Weak_Bound_Ptr (X *p) : counter_ (COUNTER::create_weak ()), ptr_ (p) { } template inline ACE_Weak_Bound_Ptr::ACE_Weak_Bound_Ptr (const ACE_Weak_Bound_Ptr &r) : counter_ (r.counter_), ptr_ (r.ptr_) { COUNTER::attach_weak (this->counter_); } template inline ACE_Weak_Bound_Ptr::ACE_Weak_Bound_Ptr (const ACE_Strong_Bound_Ptr &r) : counter_ (r.counter_), ptr_ (r.ptr_) { COUNTER::attach_weak (this->counter_); } template inline ACE_Weak_Bound_Ptr::~ACE_Weak_Bound_Ptr (void) { COUNTER::detach_weak (this->counter_); } template inline void ACE_Weak_Bound_Ptr::operator = (const ACE_Weak_Bound_Ptr &rhs) { // This will work if &rhs == this, by first increasing the ref count COUNTER *new_counter = rhs.counter_; COUNTER::attach_weak (new_counter); COUNTER::detach_weak (this->counter_); this->counter_ = new_counter; this->ptr_ = rhs.ptr_; } template inline void ACE_Weak_Bound_Ptr::operator = (const ACE_Strong_Bound_Ptr &rhs) { // This will work if &rhs == this, by first increasing the ref count COUNTER *new_counter = rhs.counter_; COUNTER::attach_weak (new_counter); COUNTER::detach_weak (this->counter_); this->counter_ = new_counter; this->ptr_ = rhs.ptr_; } template inline bool ACE_Weak_Bound_Ptr::operator== (const ACE_Weak_Bound_Ptr &r) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return r.ptr_ == 0; return this->ptr_ == r.ptr_; } template inline bool ACE_Weak_Bound_Ptr::operator== (const ACE_Strong_Bound_Ptr &r) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return r.ptr_ == 0; return this->ptr_ == r.ptr_; } template inline bool ACE_Weak_Bound_Ptr::operator== (X *p) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return p == 0; return this->ptr_ == p; } template inline bool ACE_Weak_Bound_Ptr::operator!= (const ACE_Weak_Bound_Ptr &r) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return r.ptr_ != 0; return this->ptr_ != r.ptr_; } template inline bool ACE_Weak_Bound_Ptr::operator!= (const ACE_Strong_Bound_Ptr &r) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return r.ptr_ != 0; return this->ptr_ != r.ptr_; } template inline bool ACE_Weak_Bound_Ptr::operator!= (X *p) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return p != 0; return this->ptr_ != p; } template inline ACE_Strong_Bound_Ptr ACE_Weak_Bound_Ptr::operator-> (void) const { return ACE_Strong_Bound_Ptr (*this); } template inline ACE_Strong_Bound_Ptr ACE_Weak_Bound_Ptr::strong (void) const { return ACE_Strong_Bound_Ptr (*this); } template inline X* ACE_Weak_Bound_Ptr::unsafe_get (void) const { // We do not check if the object has been deleted, since this operation // is defined to be unsafe! return this->ptr_; } template inline int ACE_Weak_Bound_Ptr::null (void) const { // A weak pointer must behave as though it is automatically set to null // if the underlying object has been deleted. if (COUNTER::object_was_deleted (this->counter_)) return 1; return this->ptr_ == 0; } template inline void ACE_Weak_Bound_Ptr::reset (X *p) { COUNTER *old_counter = this->counter_; this->counter_ = COUNTER::create_weak (); this->ptr_ = p; COUNTER::detach_weak (old_counter); } template inline int ACE_Weak_Bound_Ptr::add_ref () { return COUNTER::attach_strong (counter_); } template inline int ACE_Weak_Bound_Ptr::remove_ref () { int new_obj_ref_count = COUNTER::detach_strong (counter_); if (new_obj_ref_count == 0) { delete this->ptr_; this->ptr_ = 0; } return new_obj_ref_count; } ACE_END_VERSIONED_NAMESPACE_DECL