Download | Plain Text | No Line Numbers


  1. /**
  2.  * @module shared_ptr
  3.  * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
  4.  * @brief Class template shared_ptr
  5.  * @date 13.06.2009
  6.  */
  7.  
  8. #ifndef SHARED_PTR_H
  9. #define SHARED_PTR_H
  10.  
  11. #include <algorithm>
  12.  
  13. #undef SOLVED_1
  14. #define SOLVED_1
  15.  
  16. namespace Ti
  17. {
  18. /**
  19.   * @class shared_ptr
  20.   *
  21.   * The templates stores a pointer, usually obtained via new.
  22.   * shared_ptr implements semantics of shared ownership; the last remaining
  23.   * owner of the pointer is responsible for destroying the object, or
  24.   * otherwise releasing the resources associated with the stored pointer.
  25.   * A shared_ptr object is empty if it does not own a pointer.
  26.   */
  27. template <typename T>
  28. class shared_ptr
  29. {
  30. private:
  31. /** stored pointer */
  32. T* m_ptr;
  33. /** reference counter */
  34. unsigned long* m_count;
  35.  
  36. public:
  37. /**
  38.   * @method shared_ptr
  39.   * @brief Default ctor
  40.   * @param -
  41.   * @return -
  42.   * @globalvars none
  43.   * @exception none
  44.   * @pre none
  45.   * @post get() == m_count == NULL
  46.   */
  47. shared_ptr()
  48. : m_ptr(NULL), m_count(NULL)
  49. {}
  50.  
  51. /**
  52.   * @method get
  53.   * @brief Returns pointer of enclosed object
  54.   * @param -
  55.   * @return returns the stored pointer, null pointer if *this is empty.
  56.   * @globalvars none
  57.   * @exception none
  58.   * @pre none
  59.   * @post none
  60.   */
  61. T* get() const
  62. {
  63. return m_ptr;
  64. }
  65.  
  66. /**
  67.   * @method shared_ptr
  68.   * @brief Copy ctor. If r is empty, constructs an empty shared_ptr
  69.   * object - otherwise, constructs a shared_ptr object that
  70.   * shares ownership with r.
  71.   * @param other instance to copy from
  72.   * @return -
  73.   * @globalvars none
  74.   * @exception none
  75.   * @pre none
  76.   * @post get() == other.get() && m_count == other.m_count
  77.   */
  78. shared_ptr(const shared_ptr<T>& other)
  79. : m_ptr(other.m_ptr), m_count(other.m_count)
  80. {
  81. add_ref();
  82. }
  83.  
  84. /**
  85.   * @method shared_ptr
  86.   * @brief Copy ctor. If other is empty, constructs an empty shared_ptr
  87.   * object - otherwise, constructs a shared_ptr object that
  88.   * shares ownership with other.
  89.   * @param other instance to copy from
  90.   * @return -
  91.   * @globalvars none
  92.   * @exception none
  93.   * @pre The constructor shall not participate in the overload
  94.   * resolution unless O* is implicitly convertible to T*.
  95.   * @post get() == other.get() && m_count == other.m_count
  96.   */
  97. template <typename O>
  98. shared_ptr(const shared_ptr<O>& other)
  99. : m_ptr(other.m_ptr), m_count(other.m_count)
  100. {
  101. add_ref();
  102. }
  103.  
  104. /**
  105.   * @method shared_ptr
  106.   * @brief Copy ctor. Constructs a shared_ptr instance that stores ptr
  107.   * and shares ownership with other.
  108.   * @param other instance to copy from
  109.   * @param ptr ptr to store
  110.   * @return -
  111.   * @globalvars none
  112.   * @exception none
  113.   * @pre none
  114.   * @post get() == p && m_count == other.m_count
  115.   */
  116. template <typename O>
  117. shared_ptr(const shared_ptr<O>& other, T* ptr)
  118. : m_ptr(ptr), m_count(other.m_count)
  119. {
  120. add_ref();
  121. }
  122.  
  123. /**
  124.   * @method shared_ptr
  125.   * @brief Copy ctor. Constructs a shared_ptr object that owns the pointer p.
  126.   * @param p pointer to store
  127.   * @return -
  128.   * @globalvars none
  129.   * @exception bad_alloc if memory couldn't be optained
  130.   * @pre p shall be convertible to T*. Y shall be a complete type. The
  131.   * expression delete p shall be well formed, shall have well
  132.   * defined behavior, and shall not throw exceptions.
  133.   * @post get() == p && m_count == 1
  134.   */
  135. template <typename O>
  136. explicit shared_ptr(O* p)
  137. : m_ptr(p), m_count(new unsigned long(1))
  138. {}
  139.  
  140. /**
  141.   * @method operator=
  142.   * @brief operator =
  143.   * @param other object to compare with
  144.   * @return always *this
  145.   * @globalvars none
  146.   * @exception none
  147.   * @pre none
  148.   * @post none
  149.   */
  150. shared_ptr& operator=(const shared_ptr<T>& other)
  151. {
  152. if (*this == other)
  153. return *this;
  154. release();
  155. m_ptr = other.m_ptr;
  156. m_count = other.m_count;
  157. add_ref();
  158. return *this;
  159. }
  160.  
  161. /**
  162.   * @method operator=
  163.   * @brief operator =
  164.   * @param other object to compare with
  165.   * @return always *this
  166.   * @globalvars none
  167.   * @exception none
  168.   * @pre none
  169.   * @post none
  170.   */
  171. template <typename O>
  172. shared_ptr& operator=(const shared_ptr<O>& other)
  173. {
  174. if (*this == other)
  175. return *this;
  176. release();
  177. m_ptr = other.m_ptr;
  178. m_count = other.m_count;
  179. add_ref();
  180. return *this;
  181. }
  182.  
  183. /**
  184.   * @method ~shared_ptr
  185.   * @brief Dtor
  186.   * @param -
  187.   * @return -
  188.   * @globalvars none
  189.   * @exception none
  190.   * @pre none
  191.   * @post none
  192.   */
  193. ~shared_ptr()
  194. {
  195. release();
  196. }
  197.  
  198. /**
  199.   * @method operator*
  200.   * @brief operator *
  201.   * @param -
  202.   * @return returns *get()
  203.   * @globalvars none
  204.   * @exception none
  205.   * @pre get() != NULL
  206.   * @post none
  207.   */
  208. T& operator*() const
  209. {
  210. return *m_ptr;
  211. }
  212.  
  213. /**
  214.   * @method operator->
  215.   * @brief operator ->
  216.   * @param -
  217.   * @return returns get()
  218.   * @globalvars none
  219.   * @exception none
  220.   * @pre get() != NULL
  221.   * @post none
  222.   */
  223. T* operator->() const
  224. {
  225. return m_ptr;
  226. }
  227.  
  228. /**
  229.   * @method swap
  230.   * @brief Exchanges the contents of *this and other.
  231.   * @param other instance to swap with
  232.   * @return -
  233.   * @globalvars none
  234.   * @exception none
  235.   * @pre none
  236.   * @post none
  237.   */
  238. void swap(shared_ptr<T>& other)
  239. {
  240. std::swap(m_ptr, other.m_ptr);
  241. std::swap(m_count, other.m_count);
  242. }
  243.  
  244. /**
  245.   * @method reset
  246.   * @brief Equivalent to shared_ptr().swap(*this).
  247.   * @param -
  248.   * @return -
  249.   * @globalvars none
  250.   * @exception none
  251.   * @pre none
  252.   * @post none
  253.   */
  254. inline void reset()
  255. {
  256. shared_ptr().swap(*this);
  257. }
  258.  
  259. private:
  260. /**
  261.   * @method add_ref
  262.   * @brief Increase reference counter
  263.   * @param -
  264.   * @return -
  265.   * @globalvars none
  266.   * @exception none
  267.   * @pre m_count != NULL
  268.   * @post none
  269.   */
  270. void add_ref()
  271. {
  272. if (m_count != NULL)
  273. ++(*m_count);
  274. }
  275.  
  276. /**
  277.   * @method release
  278.   * @brief Decrease reference counter
  279.   * if m_count == 0 free all resources
  280.   * @param -
  281.   * @return -
  282.   * @globalvars none
  283.   * @exception none
  284.   * @pre m_ptr != NULL && m_count != NULL
  285.   * @post none
  286.   */
  287. void release()
  288. {
  289. if (m_ptr != NULL)
  290. {
  291. --(*m_count);
  292. if (*m_count == 0)
  293. {
  294. delete m_ptr;
  295. delete m_count;
  296. }
  297. }
  298. }
  299.  
  300. template<class O> friend class shared_ptr;
  301.  
  302. template <typename R, typename... Args>
  303. friend shared_ptr<R> make_shared(Args...);
  304.  
  305. template<typename U1, typename U2>
  306. friend bool operator==(const shared_ptr<U1>& a, const shared_ptr<U2>& b);
  307.  
  308. template<typename U1, typename U2>
  309. friend bool operator==(const shared_ptr<U1>& a, const U2* b);
  310.  
  311. template<typename U1, typename U2>
  312. friend bool operator==(const U1* a, const shared_ptr<U2>& b);
  313.  
  314. template<typename U1, typename U2>
  315. friend bool operator!=(const shared_ptr<U1>& a, const U2* b);
  316.  
  317. template<typename U1, typename U2>
  318. friend bool operator!=(const U1* a, const shared_ptr<U2>& b);
  319.  
  320. template<typename U1, typename U2>
  321. friend bool operator!=(const shared_ptr<U1>& a, const shared_ptr<U2>& b);
  322.  
  323. template <typename R, typename F>
  324. friend shared_ptr<R> shared_dynamic_cast(const shared_ptr<F>& from);
  325. };
  326.  
  327. /**
  328.   * @method make_shared
  329.   * @brief Creates an instance of shared_ptr containing a pointer to the
  330.   * also created instance of T(args...).
  331.   * @param args arguments for ctor of T.
  332.   * @return A shared_ptr instance that stores and owns the address of the
  333.   * newly constructed object of type T.
  334.   * @globalvars none
  335.   * @exception bad_alloc
  336.   * @pre none
  337.   * @post get() != 0 && use_count() == 1
  338.   */
  339. template <typename T, typename ... Args>
  340. shared_ptr<T> make_shared(Args ... args)
  341. {
  342. return shared_ptr<T>(new T(args ...));
  343. }
  344.  
  345. /**
  346.   * @method operator==
  347.   * @brief operator ==
  348.   * @param a object1 to compare
  349.   * @param b object2 to compare
  350.   * @return true if both objects contain the same pointer, false otherwise.
  351.   * @globalvars none
  352.   * @exception none
  353.   * @pre none
  354.   * @post none
  355.   */
  356. template<typename U1, typename U2>
  357. bool operator==(const shared_ptr<U1>& a, const shared_ptr<U2>& b)
  358. {
  359. return a.get() == b.get();
  360. }
  361.  
  362. /**
  363.   * @method operator==
  364.   * @brief operator ==
  365.   * @param a shared_ptr to compare
  366.   * @param b pointer to compare
  367.   * @return true if a contains pointer b, false otherwise.
  368.   * @globalvars none
  369.   * @exception none
  370.   * @pre none
  371.   * @post none
  372.   */
  373. template<typename U1, typename U2>
  374. bool operator==(const shared_ptr<U1>& a, const U2* b)
  375. {
  376. return a.get() == b;
  377. }
  378.  
  379. /**
  380.   * @method operator==
  381.   * @brief operator ==
  382.   * @param a pointer to compare
  383.   * @param b shared_ptr to compare
  384.   * @return true if b contains pointer a, false otherwise.
  385.   * @globalvars none
  386.   * @exception none
  387.   * @pre none
  388.   * @post none
  389.   */
  390. template<typename U1, typename U2>
  391. bool operator==(const U1* a, const shared_ptr<U2>& b)
  392. {
  393. return a == b.get();
  394. }
  395.  
  396. /**
  397.   * @method operator!=
  398.   * @brief operator !=
  399.   * @param a shared_ptr to compare
  400.   * @param b pointer to compare
  401.   * @return true if a contains different pointer than b, false otherwise.
  402.   * @globalvars none
  403.   * @exception none
  404.   * @pre none
  405.   * @post none
  406.   */
  407. template<typename U1, typename U2>
  408. bool operator!=(const shared_ptr<U1>& a, const U2* b)
  409. {
  410. return a.get() != b;
  411. }
  412.  
  413. /**
  414.   * @method operator!=
  415.   * @brief operator !=
  416.   * @param a pointer to compare
  417.   * @param b shared_ptr to compare
  418.   * @return true if b contains different pointer than a, false otherwise.
  419.   * @globalvars none
  420.   * @exception none
  421.   * @pre none
  422.   * @post none
  423.   */
  424. template<typename U1, typename U2>
  425. bool operator!=(const U1* a, const shared_ptr<U2>& b)
  426. {
  427. return a != b.get();
  428. }
  429.  
  430. /**
  431.   * @method operator!=
  432.   * @brief operator !=
  433.   * @param a object1 to compare
  434.   * @param b object2 to compare
  435.   * @return true if both objects contain different pointers, false otherwise.
  436.   * @globalvars none
  437.   * @exception none
  438.   * @pre none
  439.   * @post none
  440.   */
  441. template<typename U1, typename U2>
  442. bool operator!=(const shared_ptr<U1>& a, const shared_ptr<U2>& b)
  443. {
  444. return a.get() != b.get();
  445. }
  446.  
  447. /**
  448.   * @method shared_dynamic_cast
  449.   * @brief Converts pointer from F to T by using dynamic_cast.
  450.   * @param from object to cast
  451.   * @return When dynamic_cast<T*>(from.get()) returns a nonzero value,
  452.   * a shared_ptr<T> object that stores a copy of it and shares
  453.   * ownership with from - otherwise an empty shared_ptr<T> object.
  454.   * @globalvars none
  455.   * @exception none
  456.   * @pre The expression shared_dynamic_cast<T*>(from.get()) shall be well
  457.   * formed and shall have well defined behavior.
  458.   * @post w.get() == dynamic_cast<T*>(from.get()), where w is the return value.
  459.   */
  460. template <typename T, typename F>
  461. shared_ptr<T> shared_dynamic_cast(const shared_ptr<F>& from)
  462. {
  463. T* castptr = dynamic_cast<T *>(from.get());
  464. if (castptr != NULL)
  465. return shared_ptr<T>(from, castptr);
  466. else
  467. return shared_ptr<T>();
  468. }
  469. } // end namespace ti
  470.  
  471. namespace std
  472. {
  473. using namespace Ti;
  474.  
  475. /**
  476.   * @method swap
  477.   * @brief Exchanges the contents of t1 and t2.
  478.   * @param t1 instance#1 of shared_ptr
  479.   * @param t2 instance#2 of shared_ptr
  480.   * @return -
  481.   * @globalvars none
  482.   * @exception none
  483.   * @pre none
  484.   * @post none
  485.   */
  486. template <typename T>
  487. inline void swap(shared_ptr<T>& t1, shared_ptr<T>& t2)
  488. {
  489. t1.swap(t2);
  490. }
  491. }
  492.  
  493. #endif
  494.  
  495. /* vim: set et sw=2 ts=2: */
  496.