00001 /** 00002 * \file Pointer.h 00003 * \brief A NULL-initialized pointer to an \imp Object. 00004 * 00005 * Copyright 2007-2010 IMP Inventors. All rights reserved. 00006 * 00007 */ 00008 00009 #ifndef IMP_POINTER_H 00010 #define IMP_POINTER_H 00011 00012 00013 #include "WeakPointer.h" 00014 #include "RefCounted.h" 00015 #include "Object.h" 00016 #include "internal/ref_counting.h" 00017 #include "internal/OwnerPointer.h" 00018 00019 #include <boost/static_assert.hpp> 00020 #include <boost/type_traits.hpp> 00021 00022 IMP_BEGIN_NAMESPACE 00023 00024 //! A reference counted pointer to an object. 00025 /** Any time you store an Object in a C++ program, you should use a 00026 Pointer, rather than a raw C++ pointer. Using a pointer manages 00027 the reference counting and makes sure that the object is not deleted 00028 prematurely when, for example, all Python references go away and that 00029 it is deleted properly if an exception is thrown during the function. 00030 Use the IMP_NEW() macro to aid creation of pointers to new objects. 00031 00032 For example, when implementing a Restraint that uses a PairScore, 00033 store the PairScore like this: 00034 \code 00035 Pointer<PairScore> ps_; 00036 \endcode 00037 When setting up restraints you should write code like this: 00038 \code 00039 IMP_NEW(IMP::core::Harmonic, h, (0,1)); 00040 IMP::Pointer<IMP::em::DensityMap> map= IMP::em::read_map("file_name.mrc"); 00041 IMP_NEW(IMP::core::DistancePairScore, dps, (h)); 00042 \endcode 00043 which is equivalent to 00044 \code 00045 IMP::Pointer<IMP::core::Harmonic> h= new IMP::core::Harmonic(0,1); 00046 IMP::Pointer<IMP::em::DensityMap> map= IMP::em::read_map("file_name.mrc"); 00047 IMP::Pointer<IMP::core::DistancePairScore> dps 00048 = new IMP::core::DistancePairScore(h); 00049 \endcode 00050 If IMP::em::read_map() fails because the file is not found (and throws an 00051 exception), \c h is deleted. 00052 00053 The object being pointed to must inherit from IMP::RefCountedObject. 00054 Use an IMP::WeakPointer to break cycles or to point to 00055 non-ref-counted objects. 00056 00057 \param[in] O The type of IMP::RefCounted-derived object to point to 00058 */ 00059 template <class O> 00060 class Pointer: public WeakPointer<O> 00061 { 00062 // Make sure O is not RefCounted itself as RefCounted is not polymorphic 00063 BOOST_STATIC_ASSERT((!boost::is_base_of<O, RefCounted>::value)); 00064 00065 void check(const RefCounted *){} 00066 void check(const Object *o) { 00067 if (o) IMP_CHECK_OBJECT(o); 00068 } 00069 00070 typedef WeakPointer<O> P; 00071 typedef Pointer<O> This; 00072 00073 void set_pointer(O* p) { 00074 if (p == P::o_) return; 00075 if (P::o_) internal::unref(P::o_); 00076 if (p) internal::ref(p); 00077 check(p); 00078 P::o_=p; 00079 } 00080 // issue with commas 00081 BOOST_STATIC_ASSERT((boost::is_base_of<RefCounted, O>::value)); 00082 00083 public: 00084 /** copy constructor */ 00085 Pointer(const Pointer &o) { 00086 set_pointer(o.o_); 00087 } 00088 /** copy from another */ 00089 Pointer& operator=(const Pointer &o){ 00090 set_pointer(o.o_); 00091 return *this; 00092 } 00093 //! initialize to NULL 00094 Pointer() {} 00095 /** initialize from a pointer */ 00096 Pointer(O* o) { 00097 IMP_INTERNAL_CHECK(o, "Can't initialize with NULL pointer"); 00098 set_pointer(o); 00099 } 00100 /** drop control of the object */ 00101 ~Pointer(){ 00102 set_pointer(NULL); 00103 } 00104 00105 //! Set it from a possibly NULL pointer. 00106 Pointer<O>& operator=(O* o) { 00107 set_pointer(o); 00108 return *this; 00109 } 00110 //! Relinquish control of the pointer 00111 /** This must be the only pointer pointing to the object. Its 00112 reference count will be 0 after the function is called, but 00113 the object will not be destroyed. Use this to safely return 00114 objects allocated within functions. 00115 */ 00116 O* release() { 00117 internal::release(P::o_); 00118 O* ret=P::o_; 00119 P::o_= NULL; 00120 return ret; 00121 } 00122 }; 00123 00124 IMP_END_NAMESPACE 00125 00126 #endif /* IMP_POINTER_H */