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.

467 lines
12 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * AutoPointers smart pointer classes library.
  8. *
  9. * Abstract:
  10. *
  11. * Implements AutoArray and AutoPointer smart pointer classes.
  12. *
  13. * Notes:
  14. *
  15. * To avoid cleanup code in our functions we need to use smart pointer classes
  16. * for holding allocation results. These classes are roughly similar to std::auto_ptr,
  17. * although there are differences regarding ownership, operator&, defensive code etc.
  18. *
  19. * Revision History:
  20. *
  21. * 07/18/2000 mleonov
  22. * Created it.
  23. *
  24. \**************************************************************************/
  25. #ifndef __AUTOPOINTERS_HPP_
  26. #define __AUTOPOINTERS_HPP_
  27. // The following 2 classes are very similar, except that:
  28. // AutoPointer uses operator delete and provides operator->
  29. // AutoArray uses operator delete[] and provides operator[]
  30. ///// AutoArray - Pointer to array of items with automatic freeing
  31. //
  32. // This class is used for storing arrays allocated using new [].
  33. // For example:
  34. //
  35. // {
  36. // AutoArray<BYTE> buffer(new BYTE[count]);
  37. // if (!buffer)
  38. // return OutOfMemory;
  39. // buffer[0] = 0;
  40. // DoSomething(buffer.Get());
  41. // // buffer is automatically deallocated
  42. // }
  43. template<class T>
  44. class AutoArray
  45. {
  46. typedef AutoArray<T> self;
  47. public:
  48. // This constructor is made explicit so that compiler
  49. // doesn't create implicit temporaries of type AutoArray<T>
  50. explicit AutoArray(T * source = 0) : Pointer(source) {}
  51. // Copy constructor and assignment operators need to ensure that
  52. // pointer is freed only once
  53. AutoArray(self & rhs) : Pointer(rhs.Release()) {}
  54. self & operator=(self & rhs)
  55. {
  56. SafeAssign(rhs.Release());
  57. return *this;
  58. }
  59. // Safe assignment for regular pointer
  60. self & operator=(T * rhs)
  61. {
  62. SafeAssign(rhs);
  63. return *this;
  64. }
  65. // Destructor is the whole point of having this class
  66. ~AutoArray()
  67. {
  68. Clear();
  69. }
  70. // This operator is for functions which allocate pointer and return it using T **
  71. T ** operator&()
  72. {
  73. Clear();
  74. Pointer = 0;
  75. return &Pointer;
  76. }
  77. // The following 2 operators are for checks for NULL
  78. operator BOOL() const
  79. {
  80. return (Pointer != 0);
  81. }
  82. BOOL operator!() const
  83. {
  84. return !Pointer;
  85. }
  86. // We disallow implicit conversion to pointer because it's dangerous,
  87. // for example we don't want people do explicitly delete underlying pointer
  88. // operator T* () const { return Pointer; }
  89. T & operator*() const
  90. {
  91. AssertNotEmpty();
  92. return *Get();
  93. }
  94. // Make indexing work the same way as for built-in arrays
  95. template <typename INDEXTYPE>
  96. T & operator[](INDEXTYPE ndx) const
  97. {
  98. AssertNotEmpty();
  99. return *(Get() + ndx);
  100. }
  101. // Obtain the underlying pointer
  102. T * Get() const
  103. {
  104. return Pointer;
  105. }
  106. // Obtain the underlying pointer and release ownership,
  107. // normally this is used to safely return the pointer from a function
  108. // and let caller take care of deallocation
  109. T * Release()
  110. {
  111. T * tmp = Pointer;
  112. Pointer = 0;
  113. return tmp;
  114. }
  115. private:
  116. // Note that one should always assign a new value to Pointer after calling Clear()
  117. void Clear()
  118. {
  119. delete[] Pointer;
  120. }
  121. void SafeAssign(T * rhs)
  122. {
  123. // We don't want to have 2 smart pointers pointing to the same object
  124. // as it will result in double free
  125. ASSERT(!(Pointer != NULL && Pointer == rhs));
  126. Clear();
  127. Pointer = rhs;
  128. }
  129. void AssertNotEmpty() const
  130. {
  131. ASSERT(Get() != 0);
  132. }
  133. T * Pointer; // underlying pointer
  134. }; // class AutoArray
  135. ///// AutoPointer - Pointer to single item with automatic freeing
  136. //
  137. // This class is used for storing objects allocated using new.
  138. // For example:
  139. //
  140. // {
  141. // AutoPointer<OBJECT> object(new OBJECT);
  142. // if (!object)
  143. // return OutOfMemory;
  144. // object->Method();
  145. // DoSomething(object.Get());
  146. // // object is automatically deallocated
  147. // }
  148. template<class T>
  149. class AutoPointer
  150. {
  151. typedef AutoPointer<T> self;
  152. public:
  153. // This constructor is made explicit so that compiler
  154. // doesn't create implicit temporaries of type AutoPointer<T>
  155. explicit AutoPointer(T * source = 0) : Pointer(source) {}
  156. // Copy constructor and assignment operators need to ensure that
  157. // pointer is freed only once
  158. AutoPointer(self & rhs) : Pointer(rhs.Release()) {}
  159. self & operator=(self & rhs)
  160. {
  161. SafeAssign(rhs.Release());
  162. return *this;
  163. }
  164. // Safe assignment for regular pointer
  165. self & operator=(T * rhs)
  166. {
  167. SafeAssign(rhs);
  168. return *this;
  169. }
  170. // Destructor is the whole point of having this class
  171. ~AutoPointer()
  172. {
  173. Clear();
  174. }
  175. // This operator is for functions which allocate pointer and return it using T **
  176. T ** operator&()
  177. {
  178. Clear();
  179. Pointer = 0;
  180. return &Pointer;
  181. }
  182. // The following 2 operators are for checks for NULL
  183. operator BOOL() const
  184. {
  185. return (Pointer != 0);
  186. }
  187. BOOL operator!() const
  188. {
  189. return !Pointer;
  190. }
  191. // We disallow implicit conversion to pointer because it's dangerous,
  192. // for example we don't want people do explicitly delete underlying pointer
  193. // operator T* () const { return Pointer; }
  194. T & operator*() const
  195. {
  196. AssertNotEmpty();
  197. return *Get();
  198. }
  199. // Allow method calls using -> notation
  200. T * operator->() const
  201. {
  202. AssertNotEmpty();
  203. return Get();
  204. }
  205. // Obtain the underlying pointer
  206. T * Get() const
  207. {
  208. return Pointer;
  209. }
  210. // Obtain the underlying pointer and release ownership,
  211. // normally this is used to safely return the pointer from a function
  212. // and let caller take care of deallocation
  213. T * Release()
  214. {
  215. T * tmp = Pointer;
  216. Pointer = 0;
  217. return tmp;
  218. }
  219. private:
  220. // Note that one should always assign a new value to Pointer after calling Clear()
  221. void Clear()
  222. {
  223. delete Pointer;
  224. }
  225. void SafeAssign(T * rhs)
  226. {
  227. // We don't want to have 2 smart pointers pointing to the same object
  228. // as it will result in double free
  229. ASSERT(!(Pointer != NULL && Pointer == rhs));
  230. Clear();
  231. Pointer = rhs;
  232. }
  233. void AssertNotEmpty() const
  234. {
  235. ASSERT(Get() != 0);
  236. }
  237. T * Pointer; // underlying pointer
  238. }; // class AutoPointer
  239. ///// AutoBuffer - Pointer to array of items with stack alloc and automatic freeing
  240. //
  241. // This class is used for creating buffers.
  242. // For example:
  243. //
  244. // {
  245. // AutoBuffer<BYTE, 100> buffer(count);
  246. // if (!buffer)
  247. // return OutOfMemory;
  248. // buffer[0] = 0;
  249. // DoSomething(buffer.Get());
  250. // // buffer is automatically deallocated
  251. // }
  252. //
  253. // Creates an array of count BYTEs. Reserves 100 bytes of stack space.
  254. // If count <= 100, the reserved stack space is used for the buffer, else
  255. // teh space is allocated on the heap.
  256. template<class T, INT StackSize>
  257. class AutoBuffer
  258. {
  259. public:
  260. // This constructor is made explicit so that compiler
  261. // doesn't create implicit temporaries of type AutoArray<T>
  262. explicit AutoBuffer(INT requestedSize = -1)
  263. : Size (requestedSize), // Allocated lazily if > StackSize
  264. Pointer (StackBuffer) // Pointer is never NULL
  265. {
  266. if (requestedSize > StackSize)
  267. {
  268. // Stack buffer is not big enough
  269. SetSize(requestedSize);
  270. }
  271. }
  272. void Clear()
  273. {
  274. if (Pointer != StackBuffer)
  275. {
  276. delete [] Pointer;
  277. }
  278. Pointer = StackBuffer;
  279. Size = -1;
  280. }
  281. void SetSize(INT size)
  282. {
  283. // Fast case if existing buffer is big enough
  284. if (size < Size || size < StackSize)
  285. {
  286. // Use existing buffer, whether it is the stack buffer or whether
  287. // it is allocated separately.
  288. Size = size;
  289. return;
  290. }
  291. if (Pointer != StackBuffer)
  292. {
  293. // Exisiting buffer is not big enough
  294. delete [] Pointer;
  295. Pointer = StackBuffer;
  296. }
  297. Size = size;
  298. if (Size > StackSize)
  299. {
  300. // Attempt to allocate a buffer bigger than stacksize.
  301. // This doesn't have to succeed. (If it fails it leaves
  302. // Size and Pointer in the defined 'unallocated' state.)
  303. T *newBuffer = new T[Size];
  304. if (newBuffer != NULL)
  305. {
  306. Pointer = newBuffer;
  307. }
  308. else
  309. {
  310. // Cannot handle requested size
  311. Size = -1; // Uninitialised
  312. }
  313. }
  314. }
  315. ~AutoBuffer()
  316. {
  317. Clear();
  318. }
  319. // The following 2 operators check whether the buffer needs allocating
  320. operator BOOL()
  321. {
  322. return initialized();
  323. }
  324. BOOL operator!()
  325. {
  326. return !initialized();
  327. }
  328. // We disallow implicit conversion to pointer because it's dangerous,
  329. // for example we don't want people do explicitly delete underlying pointer
  330. // operator T* () const { return Pointer; }
  331. // T & operator*() const { AssertNotEmpty(); return *Get(); }
  332. // Provide index checked array lookup
  333. template <typename INDEXTYPE>
  334. T & operator[](INDEXTYPE ndx)
  335. {
  336. ASSERT(ndx >= 0 && ndx < Size);
  337. return *(Pointer + ndx);
  338. }
  339. // Obtain the underlying pointer
  340. T * Get()
  341. {
  342. return Pointer;
  343. }
  344. private:
  345. BOOL initialized()
  346. {
  347. return Size >= 0 && (Size <= StackSize || Pointer != StackBuffer);
  348. }
  349. // Possible states:
  350. //
  351. // | Size <= StackSize | Size > StackSize
  352. // | ----------------- | ----------------
  353. // | |
  354. // Pointer == StackBuffer | Buffer up to StackSize | Allocation failed
  355. // ---------------------- | is available. |
  356. // | |
  357. // | |
  358. // Pointer != StackBuffer | Dynamic buffer was | Heap buffer available
  359. // ---------------------- | previously allocated | sufficient for Size.
  360. // | since when SetSize has |
  361. // | reduced required size. |
  362. //
  363. // Note that when SetSize reduces the required size after a heap buffer
  364. // has already been allocated, the spare buffer space is NOT released.
  365. // The client may call Clear() to guarantee freeing any heap buffer.
  366. //
  367. // If uninitialized, or if cleared, Size is recorded internally as -1,
  368. // and BOOL tests return false. SetSize(0) is valid, always succeeds, and
  369. // causes BOOL tests to return TRUE.
  370. INT Size; // Requested size
  371. T * Pointer; // Underlying pointer
  372. // Note: be sure to keep the following buffer pointer size aligned.
  373. T StackBuffer[StackSize]; // Note: prior pointer causes alignment
  374. }; // class AutoBuffer
  375. class AutoLock
  376. {
  377. CRITICAL_SECTION & CriticalSection;
  378. public:
  379. AutoLock(CRITICAL_SECTION & cs) : CriticalSection(cs)
  380. {
  381. ::EnterCriticalSection(&CriticalSection);
  382. }
  383. ~AutoLock()
  384. {
  385. ::LeaveCriticalSection(&CriticalSection);
  386. }
  387. };
  388. #endif // __AUTOPOINTERS_HPP_