axobjref.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. //
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Copyright 2015 Autodesk, Inc. All rights reserved.
  5. //
  6. // Use of this software is subject to the terms of the Autodesk license
  7. // agreement provided at the time of installation or download, or which
  8. // otherwise accompanies this software in either electronic or hard copy form.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. //
  12. // AXOBJREF.H
  13. //
  14. // Object reference proxy and smart pointer template classes
  15. //
  16. #ifndef __AXOBJREF_H_
  17. #define __AXOBJREF_H_
  18. #include "dbobjptr.h"
  19. #pragma pack (push, 8)
  20. #pragma warning (disable : 4786)
  21. //
  22. // ---- AcAxObjectRef Class ----
  23. //
  24. // This class provides an abstract packaging of a reference to an AcDbObject,
  25. // that is represented either as an AcDbObjectId or as an AcDbObject pointer.
  26. // This packaging allows other classes to encapsulate an AcAxObjectRef instance
  27. // instead of separate AcDbObjectId and pointer references, and to pass the
  28. // reference around as a parameter without advance knowledge of the actual
  29. // reference type.
  30. //
  31. // The following special behaviors apply to this implementation:
  32. //
  33. // 1. The AcAxObjectRef owns any pointers that it may encapsulate. Callers
  34. // should not cache any object pointers managed by an AcAxObjectRef. The
  35. // AcAxObjectRef destructor deletes objects it has pointers for if they
  36. // are not database resident.
  37. //
  38. // 2. The AcAxObjectRef does not manage the lifetime (i.e. does not own)
  39. // any AcDbObjectIds that it may encapsulate. The lifetime of the objects
  40. // referenced by AcDbObjectIds is not bound by the lifetime of the
  41. // AcAxObjectRef.
  42. //
  43. // 3. The AcAxObjectRef only encapsulates an AcDbObject pointer or an
  44. // AcDbObjectId at any given time. Placing an AcDbObjectId into an
  45. // AcAxObjectRef which already encapsulates an AcDbObject pointer causes
  46. // the object to be deleted if it is not database resident.
  47. //
  48. // 3. Copy and assignment operations are prohibited, they would violate
  49. // the "ownership" aspect of the class. Derived classes should override
  50. // copy and constructor members and declare them private.
  51. //
  52. // 4. Callers use the acquire() and release() methods to manage the
  53. // objects encapsulated by an AcAxObjectRef. There are no accessor methods
  54. // the encapsulated references. Callers must use the release() method to
  55. // obtain references to the encapsulated pointer or objectId, which
  56. // "detaches" the AcAxObjectRef from the references.
  57. class AcAxObjectRef
  58. {
  59. public:
  60. AcAxObjectRef();
  61. AcAxObjectRef(AcDbObjectId objId);
  62. AcAxObjectRef(AcDbObject *& pObj);
  63. ~AcAxObjectRef();
  64. Acad::ErrorStatus acquire(AcDbObjectId objId);
  65. Acad::ErrorStatus acquire(AcDbObject *& pObj);
  66. Acad::ErrorStatus release(AcDbObjectId& objId, AcDbObject *& pObj);
  67. bool isNull();
  68. AcDbObjectId objectId();
  69. private:
  70. // Disallow copy constructor and assignment
  71. AcAxObjectRef(AcAxObjectRef & ref);
  72. AcAxObjectRef& operator=(AcAxObjectRef & ref);
  73. void internalRelease();
  74. // Object references
  75. AcDbObjectId m_objId;
  76. AcDbObject * m_pObj;
  77. };
  78. inline
  79. AcAxObjectRef::AcAxObjectRef()
  80. : m_objId(NULL),
  81. m_pObj(NULL)
  82. {
  83. }
  84. inline
  85. AcAxObjectRef::AcAxObjectRef(AcDbObjectId objId)
  86. : m_objId(NULL),
  87. m_pObj(NULL)
  88. {
  89. acquire(objId);
  90. }
  91. inline
  92. AcAxObjectRef::AcAxObjectRef(AcDbObject *& pObj)
  93. : m_objId(NULL),
  94. m_pObj(NULL)
  95. {
  96. acquire(pObj);
  97. }
  98. inline
  99. AcAxObjectRef::~AcAxObjectRef()
  100. {
  101. internalRelease();
  102. }
  103. inline Acad::ErrorStatus
  104. AcAxObjectRef::acquire(AcDbObjectId objId)
  105. {
  106. if (objId.isNull())
  107. return Acad::eNullObjectId;// VC8:Removed extra qualifier
  108. internalRelease();
  109. m_objId = objId;
  110. return Acad::eOk;// VC8:Removed extra qualifier
  111. }
  112. inline Acad::ErrorStatus
  113. AcAxObjectRef::acquire(AcDbObject *& pObj)
  114. {
  115. if (NULL == pObj)
  116. return Acad::eNullObjectPointer;
  117. if (!pObj->objectId().isNull())
  118. return acquire(pObj->objectId());
  119. internalRelease();
  120. m_pObj = pObj;
  121. pObj = NULL;
  122. return Acad::eOk;
  123. }
  124. inline Acad::ErrorStatus
  125. AcAxObjectRef::release(AcDbObjectId& objId, AcDbObject *& pObj)
  126. {
  127. if (isNull())
  128. return Acad::eNullObjectPointer;
  129. pObj = m_pObj;
  130. objId = m_objId;
  131. m_pObj = NULL;
  132. m_objId.setNull();
  133. return Acad::eOk;
  134. }
  135. inline void
  136. AcAxObjectRef::internalRelease()
  137. {
  138. if (NULL != m_pObj)
  139. {
  140. if (m_pObj->objectId().isNull())
  141. delete m_pObj;
  142. else
  143. {
  144. // Somebody forgot to get back the pointer to close
  145. // the object
  146. //_ASSERTE(NULL == m_pObj && m_pObj->objectId().isNull());
  147. }
  148. m_pObj = NULL;
  149. }
  150. m_objId.setNull();
  151. }
  152. inline bool
  153. AcAxObjectRef::isNull()
  154. {
  155. return (NULL == m_pObj && m_objId.isNull());
  156. }
  157. inline AcDbObjectId
  158. AcAxObjectRef::objectId()
  159. {
  160. return m_objId;
  161. }
  162. // ---- Class AcAxObjectRefPtr ----
  163. //
  164. // This class provides "smart pointer" behavior for AcAxObjectRef instances,
  165. // similar to the behavior provided by the AcDbObjectPointer template class for
  166. // AcDbObjectIds. Unlike the AcDbObjectPointer class handling of non-database
  167. // resident objects, the lifetime of the referenced object is not bound to the
  168. // lifetime of the AcAxObjectRefPtr, only the open/closed state is managed by
  169. // the AcAxObjectRefPtr class.
  170. //
  171. // The following special behaviors apply to this implementation:
  172. //
  173. // 1. The object references used by the AcAxObjectRefPtr class are "owned"
  174. // by the AcAxObjectRefPtr instance for the duration of its lifetime. When
  175. // constructed the AcAxObjectRefPtr releases the AcAxObjectRef of it's
  176. // object references. As it is destroyed the AcAxObjectRefPtr returns the
  177. // ownership of these references to the AcAxObjectRef.
  178. //
  179. // 2. The objects managed by an AcAxObjectRefPtr are maintained in an
  180. // "open" state for as long as the objects are managed by the pointer
  181. // class. Open object references are "closed" when the AcAxObjectRefPtr
  182. // object is destroyed.
  183. //
  184. // 3. All of the caveats and usage notes mentioned for
  185. // AcDbObjectPointerBase in dbobjptr.h apply to this class as well.
  186. //
  187. template<class T_OBJECT>
  188. class AcAxObjectRefPtr : public AcDbObjectPointer<T_OBJECT>
  189. {
  190. public:
  191. AcAxObjectRefPtr();
  192. AcAxObjectRefPtr(AcAxObjectRef* const pRef,
  193. AcDb::OpenMode mode,
  194. bool openErased = false);
  195. ~AcAxObjectRefPtr();
  196. private:
  197. // Disallow copy constructor, assignment operator
  198. AcAxObjectRefPtr(AcAxObjectRefPtr & pObj);
  199. AcAxObjectRefPtr& operator=(AcAxObjectRefPtr & pObj);
  200. AcAxObjectRef* const m_pRef;
  201. };
  202. template<class T_OBJECT> inline
  203. AcAxObjectRefPtr<T_OBJECT>::AcAxObjectRefPtr()
  204. : AcDbObjectPointer<T_OBJECT>(),
  205. m_pRef(NULL)
  206. {}
  207. template<class T_OBJECT> inline
  208. AcAxObjectRefPtr<T_OBJECT>::AcAxObjectRefPtr(AcAxObjectRef* const pRef, AcDb::OpenMode mode, bool openErased)
  209. : m_pRef(pRef)
  210. {
  211. //_ASSERTE(NULL != pRef);
  212. if (NULL == pRef)
  213. {
  214. this->m_status = Acad::eNullObjectPointer;// VC8:Removed extra qualifier
  215. return;
  216. }
  217. // Acquire the reference as either an objectId or pointer
  218. AcDbObjectId objId = pRef->objectId();
  219. // If it is a non-null objectId just open it
  220. if (!objId.isNull())
  221. this->m_status = acdbOpenObject(this->m_ptr, objId, mode, openErased);
  222. // If it is a null objectId we will need to acquire the
  223. // pointer from the AcAxObjectRef
  224. else
  225. {
  226. AcDbObject* pTmp = NULL;
  227. m_pRef->release(objId, pTmp);
  228. // Check for downcast of AcDbObject pointer to T_OBJECT
  229. // Restore object reference if this cast fails
  230. T_OBJECT* pTyped= T_OBJECT::cast(pTmp);
  231. if (NULL == pTyped) {
  232. this->m_ptr = NULL;
  233. m_pRef->acquire(pTmp);
  234. this->m_status = Acad::eNotThatKindOfClass;
  235. }
  236. else
  237. acquire(pTyped);
  238. }
  239. }
  240. template<class T_OBJECT> inline
  241. AcAxObjectRefPtr<T_OBJECT>::~AcAxObjectRefPtr()
  242. {
  243. // If the objectid is null we need to release
  244. // our reference and store it on the AcAxObjectRef.
  245. if (NULL != this->m_ptr && this->m_ptr->objectId().isNull()) {
  246. T_OBJECT* pTmp;
  247. release(pTmp);
  248. m_pRef->acquire(reinterpret_cast<AcDbObject*&>(pTmp));
  249. }
  250. }
  251. typedef AcAxObjectRefPtr<AcDbObject> AcDbObjectRefPtr;
  252. typedef AcAxObjectRefPtr<AcDbEntity> AcDbEntityRefPtr;
  253. #pragma pack (pop)
  254. #endif