SharedHandle.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program 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 General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #ifndef D_SHARED_HANDLE_H
  36. #define D_SHARED_HANDLE_H
  37. #include <cassert>
  38. #include <iosfwd>
  39. #include <algorithm>
  40. // To Use std::tr1::shared_ptr uncomment following few lines and
  41. // comment out SharedHandle stuff.
  42. //
  43. // #include <tr1/memory>
  44. // #define SharedHandle std::tr1::shared_ptr
  45. // #define WeakHandle std::tr1::weak_ptr
  46. // using std::tr1::static_pointer_cast;
  47. // using std::tr1::dynamic_pointer_cast;
  48. namespace aria2 {
  49. typedef struct StrongRef {} StrongRef;
  50. typedef struct WeakRef {} WeakRef;
  51. class RefCount {
  52. private:
  53. size_t strongRefCount_;
  54. size_t weakRefCount_;
  55. public:
  56. RefCount():strongRefCount_(1), weakRefCount_(1) {}
  57. RefCount(const WeakRef&):strongRefCount_(0), weakRefCount_(1) {}
  58. inline void addRefCount() {
  59. ++strongRefCount_;
  60. ++weakRefCount_;
  61. }
  62. inline void addWeakRefCount() {
  63. ++weakRefCount_;
  64. }
  65. inline void releaseRefCount() {
  66. --strongRefCount_;
  67. --weakRefCount_;
  68. }
  69. inline void releaseWeakRefCount() {
  70. --weakRefCount_;
  71. }
  72. inline size_t getStrongRefCount() { return strongRefCount_; }
  73. inline size_t getWeakRefCount() { return weakRefCount_; }
  74. };
  75. class WeakCount;
  76. class SharedCount {
  77. private:
  78. friend class WeakCount;
  79. RefCount* refCount_;
  80. public:
  81. SharedCount():refCount_(new RefCount()) {}
  82. SharedCount(const SharedCount& s):refCount_(s.refCount_)
  83. {
  84. refCount_->addRefCount();
  85. }
  86. ~SharedCount() {
  87. refCount_->releaseRefCount();
  88. if(refCount_->getWeakRefCount() == 0) {
  89. delete refCount_;
  90. }
  91. }
  92. bool reassign(const SharedCount& s) {
  93. s.refCount_->addRefCount();
  94. refCount_->releaseRefCount();
  95. if(refCount_->getWeakRefCount() == 0) {
  96. delete refCount_;
  97. refCount_ = s.refCount_;
  98. return true;
  99. }
  100. size_t thisCount = refCount_->getStrongRefCount();
  101. refCount_ = s.refCount_;
  102. return thisCount == 0;
  103. }
  104. inline size_t getRefCount() const { return refCount_->getStrongRefCount(); }
  105. void swap(SharedCount& r)
  106. {
  107. std::swap(refCount_, r.refCount_);
  108. }
  109. };
  110. class WeakCount {
  111. private:
  112. RefCount* refCount_;
  113. public:
  114. WeakCount(const WeakRef& t):refCount_(new RefCount(t)) {}
  115. WeakCount(const StrongRef& t):refCount_(new RefCount()) {}
  116. WeakCount(const WeakCount& w):refCount_(w.refCount_)
  117. {
  118. refCount_->addWeakRefCount();
  119. }
  120. WeakCount(const SharedCount& s):refCount_(s.refCount_)
  121. {
  122. refCount_->addWeakRefCount();
  123. }
  124. ~WeakCount()
  125. {
  126. refCount_->releaseWeakRefCount();
  127. if(refCount_->getWeakRefCount() == 0) {
  128. delete refCount_;
  129. }
  130. }
  131. bool reassign(const SharedCount& s) {
  132. s.refCount_->addWeakRefCount();
  133. refCount_->releaseWeakRefCount();
  134. if(refCount_->getWeakRefCount() == 0) {
  135. delete refCount_;
  136. refCount_ = s.refCount_;
  137. return true;
  138. }
  139. refCount_ = s.refCount_;
  140. return false;
  141. }
  142. bool reassign(const WeakCount& s) {
  143. s.refCount_->addWeakRefCount();
  144. refCount_->releaseWeakRefCount();
  145. if(refCount_->getWeakRefCount() == 0) {
  146. delete refCount_;
  147. refCount_ = s.refCount_;
  148. return true;
  149. }
  150. refCount_ = s.refCount_;
  151. return false;
  152. }
  153. inline size_t getRefCount() const { return refCount_->getStrongRefCount(); }
  154. };
  155. template<typename T>
  156. class SharedHandle;
  157. template<typename T>
  158. class WeakHandle;
  159. template<typename T>
  160. class SharedHandle {
  161. private:
  162. template<typename T1>
  163. friend std::ostream& operator<<(std::ostream& o, const SharedHandle<T1>& sp);
  164. template<typename T1, typename T2>
  165. friend bool operator==(const SharedHandle<T1>& t1,
  166. const SharedHandle<T2>& t2);
  167. template<typename T1, typename T2>
  168. friend bool operator!=(const SharedHandle<T1>& t1,
  169. const SharedHandle<T2>& t2);
  170. template<typename T1, typename T2>
  171. friend bool operator<(const SharedHandle<T1>& t1, const SharedHandle<T2>& t2);
  172. template<typename S> friend class SharedHandle;
  173. template<typename S> friend class WeakHandle;
  174. T* obj_;
  175. SharedCount ucount_;
  176. public:
  177. SharedHandle():obj_(0), ucount_() {}
  178. explicit SharedHandle(T* obj):obj_(obj), ucount_() {}
  179. SharedHandle(const SharedHandle& t):obj_(t.obj_), ucount_(t.ucount_) {}
  180. template<typename S>
  181. SharedHandle(const SharedHandle<S>& t):obj_(t.obj_), ucount_(t.ucount_) {}
  182. template<typename S>
  183. SharedHandle(const SharedHandle<S>& t, T* p):
  184. obj_(p), ucount_(t.ucount_) {}
  185. ~SharedHandle() {
  186. if(ucount_.getRefCount() == 1) {
  187. delete obj_;
  188. }
  189. }
  190. SharedHandle& operator=(const SharedHandle& t) {
  191. if(ucount_.reassign(t.ucount_)) {
  192. delete obj_;
  193. }
  194. obj_ = t.obj_;
  195. return *this;
  196. }
  197. template<typename S>
  198. SharedHandle& operator=(const SharedHandle<S>& t) {
  199. if(ucount_.reassign(t.ucount_)) {
  200. delete obj_;
  201. }
  202. obj_ = t.obj_;
  203. return *this;
  204. }
  205. private:
  206. typedef T* SharedHandle::*unspecified_bool_type;
  207. public:
  208. operator unspecified_bool_type() const {
  209. return obj_ == 0 ? 0 : &SharedHandle::obj_;
  210. }
  211. T* operator->() const { return obj_; }
  212. T& operator*() const {
  213. assert(obj_);
  214. return *obj_;
  215. }
  216. T* get() const {
  217. return obj_;
  218. }
  219. size_t getRefCount() const {
  220. return ucount_.getRefCount();
  221. }
  222. void reset() {
  223. *this = SharedHandle();
  224. }
  225. void reset(T* t) {
  226. *this = SharedHandle(t);
  227. }
  228. void swap(SharedHandle& other)
  229. {
  230. std::swap(obj_, other.obj_);
  231. ucount_.swap(other.ucount_);
  232. }
  233. };
  234. template<typename T>
  235. void swap(SharedHandle<T>& a, SharedHandle<T>& b)
  236. {
  237. a.swap(b);
  238. }
  239. template<typename T, typename S>
  240. SharedHandle<T>
  241. dynamic_pointer_cast(const SharedHandle<S>& t) {
  242. if(T* p = dynamic_cast<T*>(t.get())) {
  243. return SharedHandle<T>(t, p);
  244. } else {
  245. return SharedHandle<T>();
  246. }
  247. }
  248. template<typename T, typename S>
  249. SharedHandle<T>
  250. static_pointer_cast(const SharedHandle<S>& t) {
  251. return SharedHandle<T>(t, static_cast<T*>(t.get()));
  252. }
  253. // Intentionally renamed obj_ as obj_x to cause error
  254. template<typename T>
  255. std::ostream& operator<<(std::ostream& o, const SharedHandle<T>& sp) {
  256. o << *sp.obj_x;
  257. return o;
  258. }
  259. template<typename T1, typename T2>
  260. bool operator==(const SharedHandle<T1>& t1, const SharedHandle<T2>& t2) {
  261. return *t1.obj_x == *t2.obj_;
  262. }
  263. template<typename T1, typename T2>
  264. bool operator!=(const SharedHandle<T1>& t1, const SharedHandle<T2>& t2) {
  265. return *t1.obj_x != *t2.obj_;
  266. }
  267. template<typename T1, typename T2>
  268. bool operator<(const SharedHandle<T1>& t1, const SharedHandle<T2>& t2) {
  269. return *t1.obj_x < *t2.obj_;
  270. }
  271. template<typename T>
  272. class WeakHandle {
  273. private:
  274. template<typename T1>
  275. friend std::ostream& operator<<(std::ostream& o, const WeakHandle<T1>& sp);
  276. template<typename T1, typename T2>
  277. friend bool operator==(const WeakHandle<T1>& t1,
  278. const WeakHandle<T2>& t2);
  279. template<typename T1, typename T2>
  280. friend bool operator!=(const WeakHandle<T1>& t1,
  281. const WeakHandle<T2>& t2);
  282. template<typename T1, typename T2>
  283. friend bool operator<(const WeakHandle<T1>& t1, const WeakHandle<T2>& t2);
  284. template<typename S> friend class WeakHandle;
  285. T* obj_;
  286. WeakCount ucount_;
  287. public:
  288. WeakHandle():obj_(0), ucount_(WeakRef()) {}
  289. explicit WeakHandle(T* obj):obj_(obj), ucount_(StrongRef()) {}
  290. WeakHandle(const WeakHandle& t):obj_(t.obj_), ucount_(t.ucount_) {}
  291. template<typename S>
  292. WeakHandle(const SharedHandle<S>& t):obj_(t.obj_), ucount_(t.ucount_) {}
  293. template<typename S>
  294. WeakHandle(const WeakHandle<S>& t, T* p):
  295. obj_(p), ucount_(t.ucount_) {}
  296. ~WeakHandle() {}
  297. WeakHandle& operator=(const WeakHandle& t) {
  298. ucount_.reassign(t.ucount_);
  299. obj_ = t.obj_;
  300. return *this;
  301. }
  302. template<typename S>
  303. WeakHandle& operator=(const SharedHandle<S>& t) {
  304. ucount_.reassign(t.ucount_);
  305. obj_ = t.obj_;
  306. return *this;
  307. }
  308. template<typename S>
  309. WeakHandle& operator=(const WeakHandle<S>& t) {
  310. ucount_.reassign(t.ucount_);
  311. obj_ = t.obj_;
  312. return *this;
  313. }
  314. T* operator->() { return obj_; }
  315. T* operator->() const { return obj_; }
  316. T& operator*() const {
  317. assert(obj_);
  318. return *obj_;
  319. }
  320. T* get() const {
  321. if(ucount_.getRefCount() == 0 || obj_ == 0) {
  322. return 0;
  323. } else {
  324. return obj_;
  325. }
  326. }
  327. size_t getRefCount() const {
  328. return ucount_.getRefCount();
  329. }
  330. void reset() {
  331. *this = WeakHandle();
  332. }
  333. };
  334. // Intentionally renamed obj_ as obj_x to cause error
  335. template<typename T>
  336. std::ostream& operator<<(std::ostream& o, const WeakHandle<T>& sp) {
  337. o << *sp.obj_x;
  338. return o;
  339. }
  340. template<typename T1, typename T2>
  341. bool operator==(const WeakHandle<T1>& t1, const WeakHandle<T2>& t2) {
  342. return *t1.obj_x == *t2.obj_;
  343. }
  344. template<typename T1, typename T2>
  345. bool operator!=(const WeakHandle<T1>& t1, const WeakHandle<T2>& t2) {
  346. return *t1.obj_x != *t2.obj_;
  347. }
  348. template<typename T1, typename T2>
  349. bool operator<(const WeakHandle<T1>& t1, const WeakHandle<T2>& t2) {
  350. return *t1.obj_x < *t2.obj_;
  351. }
  352. template<typename T, typename S>
  353. WeakHandle<T>
  354. dynamic_pointer_cast(const WeakHandle<S>& t) {
  355. if(T* p = dynamic_cast<T*>(t.get())) {
  356. return WeakHandle<T>(t, p);
  357. } else {
  358. return WeakHandle<T>();
  359. }
  360. }
  361. } // namespace aria2
  362. #endif // D_SHARED_HANDLE_H