// -*- C++ -*- //============================================================================= /** * @file Bound_Ptr.h * * $Id$ * * @author Christopher Kohlhoff * @author Boris Kolpackov */ //============================================================================= #ifndef ACE_BOUND_PTR_H #define ACE_BOUND_PTR_H #include /**/ "ace/pre.h" #include /**/ "ace/config-all.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Auto_Ptr.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL /** * @class ACE_Bound_Ptr_Counter * * @brief An ACE_Bound_Ptr_Counter object encapsulates an * object reference count. * * Do not use this class directly, use ACE_Strong_Bound_Ptr or * ACE_Weak_Bound_Ptr instead. */ template class ACE_Bound_Ptr_Counter { public: /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; ACE_Bound_Ptr_Counter (int init_obj_ref_count = 0); ~ACE_Bound_Ptr_Counter (void); /// Create a ACE_Bound_Ptr_Counter and initialize the /// reference count to indicate ownership by a strong pointer. static ACE_Bound_Ptr_Counter *create_strong (void); /// Increase both the object and counter reference counts and return /// the new object reference count. A return value of -1 indicates /// that the object has already been destroyed. static int attach_strong (ACE_Bound_Ptr_Counter *counter); /// Decreases both the object and counter reference counts and /// deletes whichever has no more references. Returns the new object /// reference count. static int detach_strong (ACE_Bound_Ptr_Counter *counter); /// Create a ACE_Bound_Ptr_Counter and initialize the /// reference count to indicate no ownership. static ACE_Bound_Ptr_Counter *create_weak (void); /// Increase the counter reference count and return argument. static void attach_weak (ACE_Bound_Ptr_Counter *counter); /// Decreases the counter reference count and deletes the counter if /// it has no more references. static void detach_weak (ACE_Bound_Ptr_Counter *counter); /// Determine whether the object has been deleted. static int object_was_deleted (ACE_Bound_Ptr_Counter *counter); private: /// Allocate a new ACE_Bound_Ptr_Counter instance, /// returning NULL if it cannot be created. static ACE_Bound_Ptr_Counter *internal_create (int init_obj_ref_count); private: /// Reference count of underlying object. Is set to -1 once the /// object has been destroyed to indicate to all weak pointers that /// it is no longer valid. int obj_ref_count_; /// Reference count of this counter. int self_ref_count_; /// Mutex variable to synchronize access to the reference counts. ACE_LOCK lock_; }; // Forward decl. template class ACE_Weak_Bound_Ptr; /** * @class ACE_Strong_Bound_Ptr * * @brief This class implements support for a reference counted * pointer. * * Assigning or copying instances of an ACE_Strong_Bound_Ptr will * automatically increment the reference count of the underlying object. * When the last instance of an ACE_Strong_Bound_Ptr that references a * particular object is destroyed or overwritten, it will invoke delete * on its underlying pointer. */ template class ACE_Strong_Bound_Ptr { public: /// Constructor that initializes an ACE_Strong_Bound_Ptr to point to the /// object \ immediately. explicit ACE_Strong_Bound_Ptr (X *p = 0); /// Constructor that initializes an ACE_Strong_Bound_Ptr by stealing /// ownership of an object from an auto_ptr. explicit ACE_Strong_Bound_Ptr (auto_ptr p); /// Copy constructor binds and to the same object. ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr &r); /// Constructor binds and to the same object. ACE_Strong_Bound_Ptr (const ACE_Weak_Bound_Ptr &r); /// Copy constructor binds and to the same object if /// Y* can be implicitly converted to X*. template ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr &r) : counter_ (r.counter_), ptr_ (dynamic_cast(r.ptr_)) { // This ctor is temporarily defined here to increase our chances // of being accepted by broken compilers. // COUNTER::attach_strong (this->counter_); } /// Destructor. ~ACE_Strong_Bound_Ptr (void); /// Assignment operator that binds and to the same object. void operator = (const ACE_Strong_Bound_Ptr &r); /// Assignment operator that binds and to the same object. void operator = (const ACE_Weak_Bound_Ptr &r); /// Assignment operator that binds and to the same object /// if Y* can be implicitly converted to X*. template ACE_Weak_Bound_Ptr& operator= (const ACE_Strong_Bound_Ptr &r) { // This operator is temporarily defined here to increase our chances // of being accepted by broken compilers. // // This will work if &r == this, by first increasing the ref count COUNTER *new_counter = r.counter_; X* new_ptr = dynamic_cast (r.ptr_); COUNTER::attach_strong (new_counter); if (COUNTER::detach_strong (this->counter_) == 0) delete this->ptr_; this->counter_ = new_counter; this->ptr_ = new_ptr; return *this; } /// Equality operator that returns @c true if both /// ACE_Strong_Bound_Ptr instances point to the same underlying /// object. /** * @note It also returns @c true if both objects have just been * instantiated and not used yet. */ bool operator == (const ACE_Strong_Bound_Ptr &r) const; /// Equality operator that returns true if the ACE_Strong_Bound_Ptr /// and ACE_Weak_Bound_Ptr objects point to the same underlying /// object. /** * @note It also returns @c true if both objects have just been * instantiated and not used yet. */ bool operator == (const ACE_Weak_Bound_Ptr &r) const; /// Equality operator that returns @c true if the /// ACE_Strong_Bound_Ptr and the raw pointer point to the same /// underlying object. bool operator == (X *p) const; /// Inequality operator, which is the opposite of equality. bool operator != (const ACE_Strong_Bound_Ptr &r) const; /// Inequality operator, which is the opposite of equality. bool operator != (const ACE_Weak_Bound_Ptr &r) const; /// Inequality operator, which is the opposite of equality. bool operator != (X *p) const; /// Redirection operator X *operator-> (void) const; /// Dereference operator X &operator * (void) const; /// Get the pointer value. X *get (void) const; /// Resets the ACE_Strong_Bound_Ptr to refer to a different /// underlying object. void reset (X *p = 0); /// Resets the ACE_Strong_Bound_Ptr to refer to a different /// underlying object, ownership of which is stolen from the /// auto_ptr. void reset (auto_ptr p); /// Allows us to check for NULL on all ACE_Strong_Bound_Ptr /// objects. int null (void) const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: typedef X X_t; // This indirection is for Borland C++. friend class ACE_Weak_Bound_Ptr; template friend class ACE_Strong_Bound_Ptr; /// The ACE_Bound_Ptr_Counter type. typedef ACE_Bound_Ptr_Counter COUNTER; /// The reference counter. COUNTER *counter_; /// The underlying object. X *ptr_; }; /** * @class ACE_Weak_Bound_Ptr * * @brief This class implements support for a weak pointer that complements * ACE_Strong_Bound_Ptr. * * Unlike ACE_Strong_Bound_Ptr, assigning or copying instances of an * ACE_Weak_Bound_Ptr will not automatically increment the reference * count of the underlying object. What ACE_Weak_Bound_Ptr does is * preserve the knowledge that the object is in fact reference * counted, and thus provides an alternative to raw pointers where * non-ownership associations must be maintained. When the last * instance of an ACE_Strong_Bound_Ptr that references a particular * object is destroyed or overwritten, the corresponding * ACE_Weak_Bound_Ptr instances are set to NULL. */ template class ACE_Weak_Bound_Ptr { public: /// Constructor that initializes an ACE_Weak_Bound_Ptr to point to /// the object \ immediately. explicit ACE_Weak_Bound_Ptr (X *p = 0); /// Copy constructor binds and to the same object. ACE_Weak_Bound_Ptr (const ACE_Weak_Bound_Ptr &r); /// Constructor binds and to the same object. ACE_Weak_Bound_Ptr (const ACE_Strong_Bound_Ptr &r); /// Destructor. ~ACE_Weak_Bound_Ptr (void); /// Assignment operator that binds and to the same object. void operator = (const ACE_Weak_Bound_Ptr &r); /// Assignment operator that binds and to the same object. void operator = (const ACE_Strong_Bound_Ptr &r); /// Equality operator that returns @c true if both /// ACE_Weak_Bound_Ptr objects point to the same underlying object. /** * @note It also returns @c true if both objects have just been * instantiated and not used yet. */ bool operator == (const ACE_Weak_Bound_Ptr &r) const; /// Equality operator that returns @c true if the ACE_Weak_Bound_Ptr /// and ACE_Strong_Bound_Ptr objects point to the same underlying /// object. /** * @note It also returns @c true if both objects have just been * instantiated and not used yet. */ bool operator == (const ACE_Strong_Bound_Ptr &r) const; /// Equality operator that returns @c true if the ACE_Weak_Bound_Ptr /// and the raw pointer point to the same underlying object. bool operator == (X *p) const; /// Inequality operator, which is the opposite of equality. bool operator != (const ACE_Weak_Bound_Ptr &r) const; /// Inequality operator, which is the opposite of equality. bool operator != (const ACE_Strong_Bound_Ptr &r) const; /// Inequality operator, which is the opposite of equality. bool operator != (X *p) const; /// Redirection operator. /** * It returns a temporary strong pointer and makes use of the * chaining properties of operator-> to ensure that the underlying * object does not disappear while you are using it. If you are * certain of the lifetimes of the object, and do not want to incur * the locking overhead, then use the unsafe_get method instead. */ ACE_Strong_Bound_Ptr operator-> (void) const; /// Obtain a strong pointer corresponding to this weak pointer. This /// function is useful to create a temporary strong pointer for /// conversion to a reference. ACE_Strong_Bound_Ptr strong (void) const; /// Get the pointer value. Warning: this does not affect the /// reference count of the underlying object, so it may disappear on /// you while you are using it if you are not careful. X *unsafe_get (void) const; /// Resets the ACE_Weak_Bound_Ptr to refer to a different underlying /// object. void reset (X *p = 0); /// Increment the reference count on the underlying object. /** * Returns the new reference count on the object. This function may * be used to integrate the bound pointers into an external * reference counting mechanism such as those used by COM or CORBA * servants. */ int add_ref (void); /// Decrement the reference count on the underlying object, which is deleted /// if the count has reached zero. /** * Returns the new reference count on the object. This function may * be used to integrate the bound pointers into an external * reference counting mechanism such as those used by COM or CORBA * servants. */ int remove_ref (void); /// Allows us to check for NULL on all ACE_Weak_Bound_Ptr objects. int null (void) const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: typedef X X_t; // This indirection is for Borland C++. friend class ACE_Strong_Bound_Ptr; /// The ACE_Bound_Ptr_Counter type. typedef ACE_Bound_Ptr_Counter COUNTER; /// The reference counter. COUNTER *counter_; /// The underlying object. X *ptr_; }; ACE_END_VERSIONED_NAMESPACE_DECL #include "ace/Bound_Ptr.inl" #include /**/ "ace/post.h" #endif /* ACE_BOUND_PTR_H */