yasper.h
上传用户:kittypts
上传日期:2018-02-11
资源大小:241k
文件大小:9k
源码类别:

PlugIns编程

开发平台:

Visual C++

  1. /*
  2.  * yasper - A non-intrusive reference counted pointer. 
  3.  *     Version: 1.04
  4.  *   
  5.  *  Many ideas borrowed from Yonat Sharon and 
  6.  *  Andrei Alexandrescu.
  7.  *
  8.  * (zlib license)
  9.  * ----------------------------------------------------------------------------------
  10.  * Copyright (C) 2005-2007 Alex Rubinsteyn
  11.  *
  12.  * This software is provided 'as-is', without any express or implied
  13.  * warranty.  In no event will the authors be held liable for any damages
  14.  * arising from the use of this software.
  15.  *
  16.  * Permission is granted to anyone to use this software for any purpose,
  17.  * including commercial applications, and to alter it and redistribute it
  18.  * freely, subject to the following restrictions:
  19.  *
  20.  * 1. The origin of this software must not be misrepresented; you must not
  21.  *    claim that you wrote the original software. If you use this software
  22.  *    in a product, an acknowledgment in the product documentation would be
  23.  *    appreciated but is not required.
  24.  * 2. Altered source versions must be plainly marked as such, and must not be
  25.  *    misrepresented as being the original software.
  26.  * 3. This notice may not be removed or altered from any source distribution.
  27.  *
  28.  * -----------------------------------------------------------------------------------
  29.  * 
  30.  * Send all questions, comments and bug reports to:
  31.  * Alex Rubinsteyn (alex.rubinsteyn {at-nospam} gmail {dot} com)
  32.  */
  33. #ifndef yasper_ptr_h
  34. #define yasper_ptr_h
  35. #include <exception>
  36. namespace yasper
  37. {
  38. struct NullPointerException : public std::exception
  39. {
  40.     NullPointerException() throw() {}
  41.     ~NullPointerException() throw() {}
  42.     const char* what() const throw()
  43.     {
  44.         return "[Yasper Exception] Attempted to dereference null pointer";
  45.     }
  46. };
  47. struct Counter 
  48. {
  49. Counter(unsigned c = 1) : count(c) {}
  50. unsigned count; 
  51. };
  52. template <typename X> 
  53. class ptr
  54. {
  55. public:
  56.     typedef X element_type;
  57. /* 
  58. ptr needs to be its own friend so ptr< X > and ptr< Y > can access
  59. each other's private data members 
  60. */ 
  61. template <class Y> friend class ptr; 
  62. /* 
  63. default constructor
  64. - don't create Counter
  65. */
  66. ptr() : rawPtr(0), counter(0) { }
  67. /*
  68. Construct from a raw pointer 
  69. */
  70. ptr(X* raw, Counter* c = 0) : rawPtr(0), counter(0)
  71. {
  72. if (raw)
  73. {
  74. rawPtr = raw; 
  75. if (c) acquire(c);
  76. else counter = new Counter;
  77. }
  78. }
  79. template <typename Y>
  80.   explicit ptr(Y* raw, Counter* c = 0) : rawPtr(0), counter(0)
  81. {
  82. if (raw)
  83. {
  84. rawPtr = static_cast<X*>( raw );
  85. if (c) acquire(c);
  86. else counter = new Counter; 
  87. }
  88. }
  89. /*
  90. Copy constructor 
  91. */
  92. ptr(const ptr< X >& otherPtr)
  93. {
  94. acquire( otherPtr.counter );
  95. rawPtr = otherPtr.rawPtr;
  96. }
  97. template <typename Y>
  98. explicit ptr(const ptr< Y >& otherPtr) : rawPtr(0), counter(0)
  99. {
  100. acquire(otherPtr.counter);
  101. rawPtr = static_cast<X*>( otherPtr.GetRawPointer());
  102. }
  103. /* 
  104. Destructor 
  105. */ 
  106. ~ptr()
  107. {
  108. release();
  109. }
  110. /*
  111. Assignment to another ptr 
  112. */
  113. ptr& operator=(const ptr< X >& otherPtr)
  114. {
  115. if (this != &otherPtr)
  116. {
  117. release();
  118. acquire(otherPtr.counter); 
  119. rawPtr = otherPtr.rawPtr; 
  120. }
  121. return *this; 
  122. }
  123. template <typename Y>
  124. ptr& operator=(const ptr< Y >& otherPtr)
  125. {
  126. if ( this != (ptr< X >*) &otherPtr )
  127. {
  128. release();
  129. acquire(otherPtr.counter);
  130. rawPtr = static_cast<X*> (otherPtr.GetRawPointer());
  131. }
  132. return *this;
  133. }
  134. /*
  135. Assignment to raw pointers is really dangerous business.
  136. If the raw pointer is also being used elsewhere,
  137. we might prematurely delete it, causing much pain.
  138. Use sparingly/with caution.
  139. */
  140. ptr& operator=(X* raw)
  141. {
  142. if (raw != rawPtr)
  143. {
  144. release();
  145. }
  146. if (raw)
  147. {
  148. counter = new Counter; 
  149. rawPtr = raw; 
  150. }
  151. return *this;
  152. }
  153. template <typename Y>
  154. ptr& operator=(Y* raw)
  155. {
  156. if (raw != rawPtr)
  157. {
  158. release();
  159. }
  160. if (raw)
  161. {
  162. counter = new Counter; 
  163. rawPtr = static_cast<X*>(raw);
  164. }
  165. return *this;
  166. }
  167. /**
  168. NOTICE: Commented by Camus. Not necesary and dangerous feature...
  169. // 
  170. // assignment to long to allow ptr< X > = NULL, 
  171. // also allows raw pointer assignment by conversion. 
  172. // Raw pointer assignment is really dangerous!
  173. // If the raw pointer is being used elsewhere, 
  174. // it will get deleted prematurely. 
  175. ptr& operator=(long num)
  176. {
  177. if (num == 0)  //pointer set to null
  178. {
  179. release(); 
  180. }
  181. else //assign raw pointer by conversion
  182. {
  183. release();
  184. counter = new Counter; 
  185. rawPtr = reinterpret_cast<X*>(num);
  186. }
  187. return *this; 
  188. **/
  189. /*
  190. Member Access
  191. */
  192. X* operator->() const 
  193. {
  194. return GetRawPointer(); 
  195. }
  196. /*
  197. Dereference the pointer
  198. */
  199. X& operator* () const 
  200. {
  201. return *GetRawPointer(); 
  202. }
  203. /*
  204. Conversion/casting operators
  205. */
  206. operator bool() const
  207. {
  208. return IsValid();
  209. }
  210. /*
  211.    implicit casts to base types of the
  212.    the pointer we're storing 
  213. */
  214. template <typename Y>
  215. operator Y*() const
  216. {
  217. return static_cast<Y*>(rawPtr);  
  218. }
  219. template <typename Y>
  220. operator const Y*() const
  221. {
  222. return static_cast<const Y*>(rawPtr);
  223. }
  224. template <typename Y>
  225. operator ptr<Y>()
  226. {
  227. //new ptr must also take our counter or else the reference counts 
  228. //will go out of sync
  229. return ptr<Y>(rawPtr, counter);
  230. }
  231. /*
  232. Provide access to the raw pointer 
  233. */
  234. X* GetRawPointer() const         
  235. {
  236. if (rawPtr == 0) throw new NullPointerException;
  237. return rawPtr;
  238. }
  239. /* 
  240. Is there only one reference on the counter?
  241. */
  242. bool IsUnique() const
  243. {
  244. if (counter && counter->count == 1) return true; 
  245. return false; 
  246. }
  247. bool IsValid() const
  248. {
  249. if (counter && rawPtr) return true;
  250. return false; 
  251. }
  252. unsigned GetCount() const
  253. {
  254. if (counter) return counter->count;
  255. return 0;
  256. }
  257. private:
  258. X* rawPtr;
  259. Counter* counter;
  260. // increment the count
  261. void acquire(Counter* c) 
  262.   counter = c;
  263. if (c)
  264. {
  265. (c->count)++;
  266. }
  267. }
  268. // decrement the count, delete if it is 0
  269. void release()
  270.         if (counter) 
  271. {
  272. (counter->count)--; 
  273. if (counter->count == 0) 
  274. {
  275. delete counter;
  276. delete rawPtr;
  277. }
  278. }
  279. counter = 0;
  280. rawPtr = 0; 
  281. }
  282. };
  283. template <typename X, typename Y>
  284. bool operator==(const ptr< X >& lptr, const ptr< Y >& rptr) 
  285. {
  286. return lptr.GetRawPointer() == rptr.GetRawPointer(); 
  287. }
  288. template <typename X, typename Y>
  289. bool operator==(const ptr< X >& lptr, Y* raw) 
  290. {
  291. return lptr.GetRawPointer() == raw ; 
  292. }
  293. /**
  294. NOTICE: Commented by Camus. Not necesary and ambiguous feature...
  295. template <typename X>
  296. bool operator==(const ptr< X >& lptr, long num)
  297. {
  298. if (num == 0 && !lptr.IsValid())  //both pointer and address are null
  299. {
  300. return true; 
  301. }
  302. else //convert num to a pointer, compare addresses
  303. {
  304. return lptr == reinterpret_cast<X*>(num);
  305. }
  306.  
  307. }
  308. **/
  309. template <typename X, typename Y>
  310. bool operator!=(const ptr< X >& lptr, const ptr< Y >& rptr) 
  311. {
  312. return ( !operator==(lptr, rptr) );
  313. }
  314. template <typename X, typename Y>
  315. bool operator!=(const ptr< X >& lptr, Y* raw) 
  316. {
  317. return ( !operator==(lptr, raw) );
  318. }
  319. /**
  320. NOTICE: Commented by Camus. Not necesary and ambiguous feature...
  321. template <typename X>
  322. bool operator!=(const ptr< X >& lptr, long num)
  323. {
  324. return (!operator==(lptr, num) ); 
  325. }
  326. **/
  327. template <typename X, typename Y>
  328. bool operator&&(const ptr< X >& lptr, const ptr< Y >& rptr)
  329. {
  330. return lptr.IsValid() &&  rptr.IsValid();
  331. }
  332. template <typename X>
  333. bool operator&&(const ptr< X >& lptr, bool rval)
  334. {
  335. return lptr.IsValid() && rval;
  336. }
  337. template <typename X>
  338. bool operator&&(bool lval, const ptr< X >& rptr)
  339. {
  340. return lval &&  rptr.IsValid();
  341. }
  342. template <typename X, typename Y>
  343. bool operator||(const ptr< X >& lptr, const ptr< Y >& rptr)
  344. {
  345. return lptr.IsValid() || rptr.IsValid();
  346. }
  347. template <typename X>
  348. bool operator||(const ptr< X >& lptr, bool rval)
  349. {
  350. return lptr.IsValid() || rval;
  351. }
  352. template <typename X>
  353. bool operator||(bool lval, const ptr< X >& rptr)
  354. {
  355. return lval || rptr.IsValid(); 
  356. }
  357. template <typename X>
  358. bool operator!(const ptr< X >& p)
  359. {
  360. return (!p.IsValid());
  361. }
  362. /* less than comparisons for storage in containers */
  363. template <typename X, typename Y>
  364. bool operator< (const ptr< X >& lptr, const ptr < Y >& rptr)
  365. {
  366. return lptr.GetRawPointer() < rptr.GetRawPointer();
  367. }
  368. template <typename X, typename Y>
  369. bool operator< (const ptr< X >& lptr, Y* raw)
  370. {
  371. return lptr.GetRawPointer() < raw;
  372. }
  373. template <typename X, typename Y>
  374. bool operator< (X* raw, const ptr< Y >& rptr)
  375. {
  376. return raw < rptr.GetRawPointer();
  377. }
  378. } //close yasper namespace
  379. #endif