// SharedDeletePolicy.h #ifndef SharedDeletePolicy_H #define SharedDeletePolicy_H // Shared policies hold a pointer to a shared policy table so that // policies created from one another point to the same table. This // table maintains the total number of policy references and the // number of those which manage their associated object. // // This class registers itself as a managing reference in that table. // // This policy always takes (shared) management. If it is copied // from another pointer, it will share the original's policy table. // If there is no table, it will attempt to take management. If this // fails, an exception is thrown. // // This policy will not relinquish management to any other policy. // // Include the AbsPolicy header if template mebers are not allowed. #ifdef DEFECT_NO_MEMBER_TEMPLATES_AT_ALL #include "ptr/AbsPolicy.h" #endif #include "ptr/SharedPolicyTable.h" #include "ptr/PtrException.h" #include #include class SharedDeletePolicy #ifdef AbsPolicy_H : public AbsPolicy #endif { private: // attributes // The table. SharedPolicyTable* _ptable; private: // Output stream. void ostr(std::ostream& stream) const; // Drop this reference from the current table. // Delete the table if there are no other references. void drop_reference() { if ( _ptable == 0 ) return; _ptable->drop_managing_reference(); if ( _ptable->get_reference_count() == 0 ) delete _ptable; } public: // Methods for policy interface. // Constructor. // This starts a new table unless the referenced address is 0. SharedDeletePolicy(const void* ptr) : _ptable( new SharedPolicyTable() ) { _ptable->add_managing_reference(); if ( ptr == 0 ) _ptable->set_invalid(); } // Constructor from another policy. // Set argument true to share management. // This will share the table in the passed policy. // The policy must have a _ptable attribute. #ifndef AbsPolicy_H template #endif SharedDeletePolicy(const void* pvd, AbsPolicy& pol) : _ptable(pol.get_shared_policy_table()) { if ( _ptable == 0 ) { if ( pol.give_management() ) { _ptable = new SharedPolicyTable(); } else { throw PtrCannotGetManagement(); //abort(); } } else { // If table already exists, make sure it already has // a managing reference. if ( _ptable->get_managing_reference_count() < 1 ) { throw PtrCannotGetManagement(); } } _ptable->add_managing_reference(); } // Destructor. ~SharedDeletePolicy() { drop_reference(); } // Assignment from the same kind of policy. SharedDeletePolicy& operator=(const SharedDeletePolicy& rhs) { if ( _ptable == rhs._ptable ) return *this; drop_reference(); _ptable = rhs._ptable; if ( _ptable != 0 ) _ptable->add_managing_reference(); return *this; } // Has management. bool has_management() const { return true; } // Take management. bool take_management() { return false; } // Give up management. bool give_management() { return false; } // Return true if this is the last managing policy for the object. bool has_last_management() const { if ( _ptable == 0 ) return false; int count = _ptable->get_managing_reference_count(); assert( count > 0 ); return count == 1; } // Policy is valid if the table is valid. bool is_valid() const { return _ptable!=0 && _ptable->is_valid(); } // Return the shared policy table. SharedPolicyTable* get_shared_policy_table() { return _ptable; } // Delete if managing pointer. template void delete_if_managing(const T* pt) { if ( has_last_management() ) delete (T*) pt; } // Output stream. friend std::ostream& operator<<(std::ostream& stream, const SharedDeletePolicy& rhs); }; #endif