summaryrefslogtreecommitdiff
path: root/utils/intrusive_refcount.hpp
blob: 4a4b01879d68e20c6bed1b665ae8de50b868e099 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#ifndef GRAEHL__SHARED__INTRUSIVE_REFCOUNT_HPP
#define GRAEHL__SHARED__INTRUSIVE_REFCOUNT_HPP

#include <boost/intrusive_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/detail/atomic_count.hpp>
#include <cassert>

/** usage:
    struct mine : public boost::instrusive_refcount<mine> {};

    boost::intrusive_ptr<mine> p(new mine());
*/

namespace boost {
// note: the free functions need to be in boost namespace, OR namespace of involved type.  this is the only way to do it.

template <class T>
class intrusive_refcount;

template <class T>
class atomic_intrusive_refcount;

template<class T>
void intrusive_ptr_add_ref(intrusive_refcount<T>* ptr)
{
    ++(ptr->refs);
}

template<class T>
void intrusive_ptr_release(intrusive_refcount<T>* ptr)
{
    if (!--(ptr->refs)) delete static_cast<T*>(ptr);
}


//WARNING: only 2^32 (unsigned) refs allowed.  hope that's ok :)
template<class T>
class intrusive_refcount : boost::noncopyable
{
 protected:
//    typedef intrusive_refcount<T> pointed_type;
    friend void intrusive_ptr_add_ref<T>(intrusive_refcount<T>* ptr);
    friend void intrusive_ptr_release<T>(intrusive_refcount<T>* ptr);
//    friend class intrusive_ptr<T>;

    intrusive_refcount(): refs(0) {}
    ~intrusive_refcount() { assert(refs==0); }

private:
    unsigned refs;
};


template<class T>
void intrusive_ptr_add_ref(atomic_intrusive_refcount<T>* ptr)
{
    ++(ptr->refs);
}

template<class T>
void intrusive_ptr_release(atomic_intrusive_refcount<T>* ptr)
{
    if(!--(ptr->refs)) delete static_cast<T*>(ptr);
}

template<class T>
class atomic_intrusive_refcount : boost::noncopyable
{
 protected:
    friend void intrusive_ptr_add_ref<T>(atomic_intrusive_refcount<T>* ptr);
    friend void intrusive_ptr_release<T>(atomic_intrusive_refcount<T>* ptr);

    atomic_intrusive_refcount(): refs(0) {}
    ~atomic_intrusive_refcount() { assert(refs==0); }

private:
    boost::detail::atomic_count refs;
};

}


#endif