removed unused stuff in in_loop_invoke.hpp
[beacon-ss.git] / beacon / intrusive_ptr.hpp
blob1893a8aa87e11b8024e1ef3c7438b2ba3ed03387
1 /**
2 * beacon
3 * Author: Lukas Krejci <krejci.l@centrum.cz>, (C) 2008
4 * Copyright: See COPYING file that comes with this distribution
5 */
7 #ifndef BEACON_intrusive_ptr_H
8 #define BEACON_intrusive_ptr_H
10 #include <beacon/reference_countable.hpp>
11 #include <functional> // for std::less
12 #include <iosfwd> // for std::basic_ostream
14 extern "C" {
15 #include <atomic_ops.h>
18 namespace beacon {
20 /**
21 * A simple shared pointer implementation inspired by
22 * boost::intrusive_ptr that only adds a cas() operation to
23 * the usual mix of ops.
25 * It depends on two functions being overriden for type T:
26 * \c
27 * beacon_intrusive_ptr_add_ref(T *)
28 * beacon_intrusive_ptr_release(T *)
29 * \endcode
31 * The first is called when a reference count should be increased,
32 * the second when it should be decreased. It is the user's
33 * responsibility to implement those functions properly.
35 * beacon::reference_countable implements those functions so
36 * that any reference_countable instance is usable with this shared
37 * pointer implementation.
39 template<typename T>
40 class intrusive_ptr {
42 public:
43 intrusive_ptr() : _p(0) {}
45 intrusive_ptr(T * p, bool add_ref = true) : _p(p) {
46 if (_p != 0 && add_ref) {
47 beacon_intrusive_ptr_add_ref(_p);
51 intrusive_ptr(intrusive_ptr const & rhs) : _p(rhs._p) {
52 if (_p != 0) beacon_intrusive_ptr_add_ref(_p);
55 ~intrusive_ptr() {
56 if (_p != 0) beacon_intrusive_ptr_release(_p);
59 intrusive_ptr & operator=(intrusive_ptr const & rhs) {
60 intrusive_ptr<T>(rhs).swap(*this);
61 return *this;
64 intrusive_ptr & operator=(T * rhs) {
65 intrusive_ptr<T>(rhs).swap(*this);
66 return *this;
69 T * get() const {
70 return _p;
73 T & operator*() const {
74 return *_p;
77 T * operator->() const {
78 return _p;
81 void swap(intrusive_ptr & rhs) {
82 T * tmp = _p;
83 _p = rhs._p;
84 rhs._p = tmp;
87 typedef T * intrusive_ptr<T>::*unspecified_bool_type;
89 operator unspecified_bool_type () const {
90 return _p == 0? 0: &intrusive_ptr<T>::_p;
93 /**
94 * Atomically does:
95 * \code
96 * if (this == cmp) {
97 * this = xchg;
98 * return true;
99 * }
100 * return false;
101 * \endcode
103 * @p cmp the shared_ptr to compare with
104 * @p xchg the shared_ptr to change this instance to
106 bool cas(intrusive_ptr<T> & cmp, intrusive_ptr<T> & xchg) {
107 AO_t * my_ao = (AO_t *)(&_p);
108 AO_t cmp_ao = (AO_t)(cmp.get());
109 AO_t xchg_ao = (AO_t)(xchg.get());
111 if (AO_compare_and_swap(my_ao, cmp_ao, xchg_ao)) {
112 //I assigned the xchg pointer to me, tossing away
113 //my former reference that used to be the same as cmp's.
114 beacon_intrusive_ptr_add_ref(_p);
115 beacon_intrusive_ptr_release((T *)cmp_ao);
117 return true;
120 return false;
123 private:
124 T * _p;
127 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
129 return a.get() == b.get();
132 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
134 return a.get() != b.get();
137 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
139 return a.get() == b;
142 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
144 return a.get() != b;
147 template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
149 return a == b.get();
152 template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
154 return a != b.get();
157 template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
159 return std::less<T *>()(a.get(), b.get());
162 template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
164 lhs.swap(rhs);
167 // mem_fn support
169 template<class T> T * get_pointer(intrusive_ptr<T> const & p)
171 return p.get();
174 template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
176 return static_cast<T *>(p.get());
179 template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
181 return const_cast<T *>(p.get());
184 template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
186 return dynamic_cast<T *>(p.get());
189 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
191 os << p.get();
192 return os;
195 } //namespace beacon
197 #endif