1 /* 2 This file is part of Caelum. 3 See http://www.ogre3d.org/wiki/index.php/Caelum 4 5 Copyright (c) 2008 Caelum team. See Contributors.txt for details. 6 7 Caelum is free software: you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published 9 by the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 Caelum is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with Caelum. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef CAELUM__PRIVATE_PTR_H 22 #define CAELUM__PRIVATE_PTR_H 23 24 #include "CaelumPrerequisites.h" 25 26 namespace Caelum 27 { 28 /** Default traits for Caelum::PrivatePtr. 29 * 30 * This default traits class make PrivatePtr work like std::auto_ptr. 31 * Other Traits classes can derive from this and only customize some of 32 * the functions. 33 * 34 * @see PrivatePtr 35 */ 36 template<class PointedT> 37 struct DefaultPrivatePtrTraits 38 { 39 /// The type of the inner member to hold in PrivatePtr 40 typedef PointedT* InnerPointerType; 41 42 /// Return an InnerPointerType repressenting a null value. getNullValueDefaultPrivatePtrTraits43 static inline const InnerPointerType getNullValue() { 44 return 0; 45 } 46 47 /// Convert InnerPointerType to a naked PointedT. getPointerDefaultPrivatePtrTraits48 static inline PointedT* getPointer (const InnerPointerType& inner) { 49 return inner; 50 } 51 52 /// Destroy the inner value (and set null). destroyDefaultPrivatePtrTraits53 static void destroy (InnerPointerType& inner) 54 { 55 delete inner; 56 inner = 0; 57 } 58 }; 59 60 /** Template for smart pointers with strict unique ownership. 61 * A lot of objects in Ogre are created and destroyed through other 62 * "Manager" objects. Even though the memory for such objects is never 63 * actually leaked better lifetime control is frequently useful. 64 * 65 * PrivatePtr is very similar in behaviour to std::auto_ptr but tries 66 * to mimic Ogre::SharedPtr method names. Only one PrivatePtr must exist to 67 * a certain object at any one time. Assignment and copy construction will 68 * in fact pass away ownership and set the original PrivatePtr to null. 69 * 70 * This very limited functionality makes PrivatePtr very efficient; it should 71 * have no overhead compared to doing the same thing manually. 72 * 73 * PrivatePtr supports customization through a static traits class which 74 * can customize what happens when the PrivatePtr is destroyed. This makes 75 * it possible to use PrivatePtr classes for fine control over the lifetime 76 * of objects which are otherwise managed by an external class. 77 * 78 * @see DefaultPrivatePtrTraits 79 */ 80 template<class PointedT, typename TraitsT = DefaultPrivatePtrTraits<PointedT> > 81 class PrivatePtr 82 { 83 private: 84 /// Brings InnerPointerType as a type in this scope. 85 typedef typename TraitsT::InnerPointerType InnerPointerType; 86 87 /// Inner data member. 88 InnerPointerType mInner; 89 90 public: 91 /** Change the inner value. 92 * This will destroy the old value and gain ownership of the new value. 93 */ 94 void reset (const InnerPointerType& newInner = TraitsT::getNullValue()) { 95 if (mInner == newInner) { 96 return; 97 } 98 TraitsT::destroy (mInner); 99 mInner = newInner; 100 } 101 release()102 InnerPointerType release () { 103 InnerPointerType result = mInner; 104 mInner = TraitsT::getNullValue(); 105 return result; 106 } 107 108 /** Constructor; always initialize to 0. 109 */ PrivatePtr()110 PrivatePtr () { mInner = TraitsT::getNullValue (); } 111 112 /** Initializing constructur 113 */ PrivatePtr(const InnerPointerType & inner)114 PrivatePtr (const InnerPointerType& inner) { mInner = inner; } 115 116 /** Non-virtual destructor (don't derive from this). 117 */ ~PrivatePtr()118 ~PrivatePtr () { setNull(); } 119 120 /** Copy constructor; clears right-hand-side. 121 */ PrivatePtr(PrivatePtr & rhs)122 PrivatePtr (PrivatePtr& rhs) 123 { 124 if (&rhs != this) { 125 this->reset (rhs.mInner); 126 rhs.mInner = TraitsT::getNullValue (); 127 } 128 } 129 130 /** Assignment 131 */ 132 const PrivatePtr& operator= (PrivatePtr& rhs) 133 { 134 if (&rhs != this) { 135 this->reset (rhs.mInner); 136 rhs.mInner = TraitsT::getNullValue (); 137 } 138 return *this; 139 } 140 141 /// Check if this is null. isNull()142 bool isNull () const { return mInner == TraitsT::getNullValue (); } 143 144 /// Set to null and destroy contents (if any). setNull()145 void setNull () { 146 TraitsT::destroy (mInner); 147 assert(this->isNull()); 148 } 149 getPointer()150 PointedT* getPointer () const { return TraitsT::getPointer (mInner); } get()151 PointedT* get () const { return getPointer (); } 152 PointedT* operator-> () const { return getPointer (); } 153 PointedT& operator* () const{ return *getPointer (); } 154 }; 155 156 /** PrivatePtr traits for a movable object. 157 * This kind of pointer will remove the movable from the scene and destroy it. 158 */ 159 template<class MovableT> 160 struct MovableObjectPrivatePtrTraits: public DefaultPrivatePtrTraits<MovableT> 161 { 162 typedef MovableT* InnerPointerType; 163 destroyMovableObjectPrivatePtrTraits164 static void destroy (InnerPointerType& inner) 165 { 166 if (inner != 0) { 167 //Ogre::LogManager::getSingletonPtr ()->logMessage ( 168 // "PrivatePtr: Destroying movable object " + inner->getName ()); 169 inner->_getManager ()->destroyMovableObject (inner); 170 inner = 0; 171 } 172 } 173 }; 174 175 typedef PrivatePtr<Ogre::MovableObject, MovableObjectPrivatePtrTraits<Ogre::MovableObject> > PrivateMovableObjectPtr; 176 typedef PrivatePtr<Ogre::BillboardChain, MovableObjectPrivatePtrTraits<Ogre::BillboardChain> > PrivateBillboardChainPtr; 177 typedef PrivatePtr<Ogre::BillboardSet, MovableObjectPrivatePtrTraits<Ogre::BillboardSet> > PrivateBillboardSetPtr; 178 typedef PrivatePtr<Ogre::Entity, MovableObjectPrivatePtrTraits<Ogre::Entity> > PrivateEntityPtr; 179 typedef PrivatePtr<Ogre::Light, MovableObjectPrivatePtrTraits<Ogre::Light> > PrivateLightPtr; 180 typedef PrivatePtr<Ogre::ManualObject, MovableObjectPrivatePtrTraits<Ogre::ManualObject> > PrivateManualObjectPtr; 181 typedef PrivatePtr<Ogre::ParticleSystem, MovableObjectPrivatePtrTraits<Ogre::ParticleSystem> > PrivateParticleSystemPtr; 182 183 /** PrivatePtr traits for a scene node. 184 * Scene nodes are created and destroyed through the scene manager. 185 * @see PrivatePrivateSceneNodePtr 186 */ 187 struct SceneNodePrivatePtrTraits: public DefaultPrivatePtrTraits<Ogre::SceneNode> 188 { destroySceneNodePrivatePtrTraits189 static void destroy (InnerPointerType& inner) 190 { 191 if (inner) { 192 //Ogre::LogManager::getSingletonPtr ()->logMessage ( 193 // "PrivatePtr: Destroying scene node " + inner->getName ()); 194 inner->getCreator ()->destroySceneNode (inner->getName ()); 195 inner = 0; 196 } 197 } 198 }; 199 200 typedef PrivatePtr<Ogre::SceneNode, SceneNodePrivatePtrTraits> PrivateSceneNodePtr; 201 202 /** PrivatePtr traits for uniquely-owned resources. 203 * 204 * All ogre resources are tracked by a resource managed by name and can 205 * be globally referenced from multiple places. This traits class allows 206 * you to hold a pointer to a resource which you create and completely 207 * control. 208 * 209 * The best example of this is a cloned material. It is frequently useful 210 * to create a clone of an existing material and tweak settings for one 211 * particular usage. After the clone is no longer useful the material must 212 * be explicitly removed from the MaterialManager. Otherwise an unloaded 213 * resource handle is leaked. 214 * 215 * When the PrivatePtr gets out of scope the resource is removed from the 216 * manager. In debug mode this will also check that there are no other 217 * references to the destroyed resource. 218 */ 219 template<class PointedT, class InnerT, class ManagerT> 220 struct PrivateResourcePtrTraits 221 { 222 typedef InnerT InnerPointerType; 223 getNullValuePrivateResourcePtrTraits224 static const InnerT getNullValue () { 225 return InnerT(); 226 } 227 getPointerPrivateResourcePtrTraits228 static PointedT* getPointer (const InnerPointerType& inner) { 229 return inner.getPointer (); 230 } 231 destroyPrivateResourcePtrTraits232 static void destroy (InnerPointerType& inner) { 233 if (!inner.isNull ()) { 234 //Ogre::LogManager::getSingletonPtr ()->logMessage ( 235 // "PrivateResourcePtrTraits: Destroying owned resource" 236 // " name=" + inner->getName () + 237 // " handle=" + Ogre::StringConverter::toString (inner->getHandle ()) ); 238 ManagerT::getSingletonPtr ()->remove (inner->getHandle ()); 239 assert (inner.unique () && "Resource pointer not unique after destruction"); 240 inner.setNull(); 241 } 242 } 243 }; 244 245 typedef PrivatePtr < 246 Ogre::Material, 247 PrivateResourcePtrTraits < 248 Ogre::Material, 249 Ogre::MaterialPtr, 250 Ogre::MaterialManager 251 > 252 > PrivateMaterialPtr; 253 254 typedef PrivatePtr < 255 Ogre::Mesh, 256 PrivateResourcePtrTraits < 257 Ogre::Mesh, 258 Ogre::MeshPtr, 259 Ogre::MeshManager 260 > 261 > PrivateMeshPtr; 262 } 263 264 #endif // CAELUM__PRIVATE_PTR_H 265