Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
9.4 KiB

  1. /*
  2. * E X \ A U T O P T R . H
  3. *
  4. * Implementation of automatic-cleanup pointer template classes.
  5. * This implementation is safe for use in NON-throwing environments
  6. * (save for EXDAV & other store-loaded components).
  7. *
  8. * Copyright 1986-1998 Microsoft Corporation, All Rights Reserved.
  9. */
  10. //----------------------------------------------------------------------//
  11. //
  12. // Automatic pointers defined here:
  13. //
  14. // auto_ptr<>
  15. // auto_heap_ptr<>
  16. // auto_handle<>
  17. // auto_heap_array<>
  18. // auto_ref_ptr<CRefCountedObject>
  19. //
  20. #ifndef _EX_AUTOPTR_H_
  21. #define _EX_AUTOPTR_H_
  22. #include <caldbg.h>
  23. #include <calrc.h>
  24. #include <ex\exmem.h>
  25. #pragma warning(disable: 4284) // operator-> to a non UDT
  26. // ========================================================================
  27. //
  28. // TEMPLATE CLASS auto_ptr
  29. //
  30. // Stripped down auto_ptr class based on the C++ STL standard one
  31. //
  32. // Calls delete on dtor.
  33. // NO equals operator between these classes, as that hides
  34. // the transfer-of-ownership. Handle those yourself, EXPLICITLY,
  35. // like this:
  36. // auto-ptr1 = auto-ptr2.relinquish();
  37. //
  38. template<class X>
  39. class auto_ptr
  40. {
  41. protected:
  42. X * px;
  43. // NOT IMPLEMENTED
  44. //
  45. auto_ptr(const auto_ptr<X>& p);
  46. auto_ptr& operator=(const auto_ptr<X>& p);
  47. public:
  48. // CONSTRUCTORS
  49. //
  50. explicit auto_ptr(X* p=0) : px(p) {}
  51. ~auto_ptr()
  52. {
  53. delete px;
  54. }
  55. // ACCESSORS
  56. //
  57. bool operator!()const { return (px == NULL); }
  58. operator X*() const { return px; }
  59. // X& operator*() const { Assert (px); return *px; }
  60. X* operator->() const { Assert (px); return px; }
  61. X* get() const { return px; }
  62. // MANIPULATORS
  63. //
  64. X* relinquish() { X* p = px; px = 0; return p; }
  65. X** operator&() { Assert (!px); return &px; }
  66. void clear()
  67. {
  68. delete px;
  69. px = NULL;
  70. }
  71. auto_ptr& operator=(X* p)
  72. {
  73. Assert(!px); // Scream on overwrite of good data.
  74. px = p;
  75. return *this;
  76. }
  77. };
  78. // ========================================================================
  79. //
  80. // TEMPLATE CLASS auto_handle
  81. //
  82. // auto_ptr for NT system handles.
  83. //
  84. // Closes the handle on dtor.
  85. // NO equals operator between these classes, as that hides
  86. // the transfer-of-ownership. Handle those yourself, EXPLICITLY,
  87. // like this:
  88. // auto-handle-1 = auto-handle-2.relinquish();
  89. //
  90. template<class X>
  91. class auto_handle
  92. {
  93. private:
  94. X handle;
  95. // NOT IMPLEMENTED
  96. //
  97. auto_handle(const auto_handle<X>& h);
  98. auto_handle& operator=(auto_handle<X>& h);
  99. public:
  100. // CONSTRUCTORS
  101. //
  102. auto_handle(X h=0) : handle(h) {}
  103. ~auto_handle()
  104. {
  105. if (handle && INVALID_HANDLE_VALUE != handle)
  106. {
  107. CloseHandle(handle);
  108. }
  109. }
  110. // ACCESSORS
  111. //
  112. operator X() const { return handle; }
  113. X get() const { return handle; }
  114. // MANIPULATORS
  115. //
  116. X relinquish() { X h = handle; handle = 0; return h; }
  117. X* load() { Assert(NULL==handle); return &handle; }
  118. X* operator&() { Assert(NULL==handle); return &handle; }
  119. void clear()
  120. {
  121. if (handle && INVALID_HANDLE_VALUE != handle)
  122. {
  123. CloseHandle(handle);
  124. }
  125. handle = 0;
  126. }
  127. auto_handle& operator=(X h)
  128. {
  129. Assert (handle == 0); // Scream on overwrite of good data
  130. handle = h;
  131. return *this;
  132. }
  133. };
  134. // ========================================================================
  135. //
  136. // TEMPLATE CLASS auto_ref_ptr
  137. //
  138. // Holds a ref on an object. Works with CRefCountedObject.
  139. // Grabs a ref when a pointer is assigned into this object.
  140. // Releases the ref when this object is destroyed.
  141. //
  142. template<class X>
  143. class auto_ref_ptr
  144. {
  145. private:
  146. X * m_px;
  147. void init()
  148. {
  149. if ( m_px )
  150. {
  151. m_px->AddRef();
  152. }
  153. }
  154. void deinit()
  155. {
  156. if ( m_px )
  157. {
  158. m_px->Release();
  159. }
  160. }
  161. // NOT IMPLEMENTED
  162. // We turn off operator new to try to prevent auto_ref_ptrs being
  163. // created via new(). However, storext.h uses a macro to redefine new,
  164. // so this line is only used on non-DBG.
  165. #ifndef DBG
  166. void * operator new(size_t cb);
  167. #endif // !DBG
  168. public:
  169. // CONSTRUCTORS
  170. //
  171. explicit auto_ref_ptr(X* px=0) :
  172. m_px(px)
  173. {
  174. init();
  175. }
  176. auto_ref_ptr(const auto_ref_ptr<X>& rhs) :
  177. m_px(rhs.m_px)
  178. {
  179. init();
  180. }
  181. ~auto_ref_ptr()
  182. {
  183. deinit();
  184. }
  185. // ACCESSORS
  186. //
  187. X& operator*() const { return *m_px; }
  188. X* operator->() const { return m_px; }
  189. X* get() const { return m_px; }
  190. // MANIPULATORS
  191. //
  192. X* relinquish() { X* p = m_px; m_px = 0; return p; }
  193. X** load() { Assert(NULL==m_px); return &m_px; }
  194. X* take_ownership(X* p) { Assert(NULL==m_px); return m_px = p; }
  195. void clear()
  196. {
  197. deinit();
  198. m_px = NULL;
  199. }
  200. auto_ref_ptr& operator=(const auto_ref_ptr<X>& rhs)
  201. {
  202. if ( m_px != rhs.m_px )
  203. {
  204. deinit();
  205. m_px = rhs.m_px;
  206. init();
  207. }
  208. return *this;
  209. }
  210. auto_ref_ptr& operator=(X* px)
  211. {
  212. if ( m_px != px )
  213. {
  214. deinit();
  215. m_px = px;
  216. init();
  217. }
  218. return *this;
  219. }
  220. };
  221. // ========================================================================
  222. //
  223. // TEMPLATE CLASS auto_heap_ptr
  224. //
  225. // An auto_ptr class based on the heap instead of new.
  226. //
  227. // Calls ExFree() on dtor.
  228. // NO equals operator between these classes, as that hides
  229. // the transfer-of-ownership. Handle those yourself, EXPLICITLY,
  230. // like this:
  231. // auto-heap-ptr1 = auto-heap-ptr2.relinquish();
  232. //
  233. template<class X>
  234. class auto_heap_ptr
  235. {
  236. private:
  237. X * m_px;
  238. // NOT IMPLEMENTED
  239. //
  240. auto_heap_ptr (const auto_heap_ptr<X>& p);
  241. auto_heap_ptr& operator= (const auto_heap_ptr<X>& p);
  242. //void * operator new(size_t cb);
  243. public:
  244. // CONSTRUCTORS
  245. //
  246. explicit auto_heap_ptr (X* p=0) : m_px(p) {}
  247. ~auto_heap_ptr()
  248. {
  249. clear();
  250. }
  251. // ACCESSORS
  252. //
  253. // NOTE: this simple cast operator (operator X*()) allows
  254. // the [] operator to function.
  255. //$REVIEW: Should we add an explicit [] operator?
  256. operator X*() const { return m_px; }
  257. X* operator->() const { Assert (m_px); return m_px; }
  258. X* get() const { return m_px; }
  259. //X& operator[] (UINT index) const { return *(m_px + index); }
  260. //X& operator[] (UINT index) const { return m_px[index]; }
  261. // MANIPULATORS
  262. //
  263. X* relinquish() { X* p = m_px; m_px = 0; return p; }
  264. X** load() { Assert(!m_px); return &m_px; }
  265. //$REVIEW: Can we migrate all users of operator&() to use load() instead???
  266. //$REVIEW: Benefit: it's more explicit. Detriment: need to change existing code.
  267. X** operator&() { Assert (!m_px); return &m_px; }
  268. void clear()
  269. {
  270. if (m_px) // Release any object we're holding now
  271. {
  272. ExFree (m_px);
  273. }
  274. m_px = NULL;
  275. }
  276. // Realloc
  277. //$REVIEW:
  278. // This operator is technically NOT safe for store-side code!
  279. // It makes it easy to ignore memory failures.
  280. // (However, it is currently so ingrained in our vocabulary that
  281. // removing it will touch a very large number of files: )
  282. // For now, to be safe, callers MUST check the value of their
  283. // object (using .get()) after calling this function.
  284. //
  285. void realloc(UINT cb)
  286. {
  287. VOID * pvTemp;
  288. if (m_px)
  289. pvTemp = ExRealloc (m_px, cb);
  290. else
  291. pvTemp = ExAlloc (cb);
  292. Assert (pvTemp);
  293. m_px = reinterpret_cast<X*>(pvTemp);
  294. }
  295. //$REVIEW: end
  296. // Failing Realloc
  297. //
  298. BOOL frealloc(UINT cb)
  299. {
  300. VOID * pvTemp;
  301. if (m_px)
  302. pvTemp = ExRealloc (m_px, cb);
  303. else
  304. pvTemp = ExAlloc (cb);
  305. if (!pvTemp)
  306. return FALSE;
  307. m_px = static_cast<X*>(pvTemp);
  308. return TRUE;
  309. }
  310. // NOTE: This method asserts if the auto-pointer already holds a value.
  311. // Use clear() or relinquish() to clear the old value before
  312. // taking ownership of another value.
  313. //
  314. void take_ownership (X * p)
  315. {
  316. Assert (!m_px); // Scream on overwrite of good data.
  317. m_px = p;
  318. }
  319. // NOTE: This operator= is meant to do exactly the same as take_ownership().
  320. //
  321. auto_heap_ptr& operator= (X * p)
  322. {
  323. Assert (!m_px); // Scream on overwrite of good data.
  324. m_px = p;
  325. return *this;
  326. }
  327. };
  328. // ========================================================================
  329. //
  330. // TEMPLATE CLASS auto_co_task_mem
  331. //
  332. // Stripped down auto_co_task_mem class based on the C++ STL standard one
  333. //
  334. // Calls CoTaskMemFree on dtor.
  335. // NO equals operator between these classes, as that hides
  336. // the transfer-of-ownership. Handle those yourself, EXPLICITLY,
  337. // like this:
  338. // auto-co_task_mem1 = auto-co_task_mem2.relinquish();
  339. //
  340. template<class X>
  341. class auto_co_task_mem
  342. {
  343. protected:
  344. X * m_px;
  345. // NOT IMPLEMENTED
  346. //
  347. auto_co_task_mem(const auto_co_task_mem<X>& p);
  348. auto_co_task_mem& operator=(const auto_co_task_mem<X>& p);
  349. public:
  350. // CONSTRUCTORS
  351. //
  352. explicit auto_co_task_mem(X* p=0) : m_px(p) {}
  353. ~auto_co_task_mem()
  354. {
  355. CoTaskMemFree(m_px);
  356. }
  357. // ACCESSORS
  358. //
  359. X* operator->() const { Assert (m_px); return m_px; }
  360. X* get() const { return m_px; }
  361. // MANIPULATORS
  362. //
  363. X* relinquish() { X* p = m_px; m_px = 0; return p; }
  364. X** load() { Assert(!m_px); return &m_px; }
  365. X** operator&() { Assert (!m_px); return &m_px; }
  366. void clear()
  367. {
  368. CoTaskMemFree(m_px);
  369. m_px = NULL;
  370. }
  371. // NOTE: This method asserts if the auto-pointer already holds a value.
  372. // Use clear() or relinquish() to clear the old value before
  373. // taking ownership of another value.
  374. //
  375. void take_ownership (X * p)
  376. {
  377. Assert (!m_px); // Scream on overwrite of good data.
  378. m_px = p;
  379. }
  380. auto_co_task_mem& operator=(X* p)
  381. {
  382. Assert(!m_px); // Scream on overwrite of good data.
  383. m_px = p;
  384. return *this;
  385. }
  386. };
  387. #endif //!_EX_AUTOPTR_H_