Kernel Quantum Probability Library
The KQP library aims at providing tools for working with quantums probabilities
intrusive_ptr_object.hpp
1 //
2 // Copyright (c) 2006 Alexis Wilke and Doug Barbieri
3 //
4 // Modified by B. Piwowarski (November 2011): added const qualifiers to allow intrusive pointers on const objects
5 //
6 // Boost Software License - Version 1.0 - August 17th, 2003
7 //
8 // Permission is hereby granted, free of charge, to any person or organization
9 // obtaining a copy of the software and accompanying documentation covered by
10 // this license (the "Software") to use, reproduce, display, distribute,
11 // execute, and transmit the Software, and to prepare derivative works of the
12 // Software, and to permit third-parties to whom the Software is furnished to
13 // do so, all subject to the following:
14 //
15 // The copyright notices in the Software and this entire statement, including
16 // the above license grant, this restriction and the following disclaimer,
17 // must be included in all copies of the Software, in whole or in part, and
18 // all derivative works of the Software, unless such copies or derivative
19 // works are solely in the form of machine-executable object code generated by
20 // a source language processor.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
25 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
26 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
27 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 // DEALINGS IN THE SOFTWARE.
29 //
30 // Find documentation on the home website:
31 //
32 // http://boost-extras.sourceforge.net/
33 // http://boost-extras.sourceforge.net/intrusive_ptr_object/intrusive_ptr_object.html
34 //
35 #ifndef BOOST_INTRUSIVE_PTR_OBJECT
36 #define BOOST_INTRUSIVE_PTR_OBJECT 1
37 
38 
39 
40 #include <boost/assert.hpp>
41 #include <boost/intrusive_ptr.hpp>
42 // avoid thread overhead if not required/available
43 #if defined(BOOST_HAS_THREADS)
44 #include <boost/thread/mutex.hpp>
45 #endif
46 
47 #undef BOOST_HAS_THREADS
48 
49 
50 // place these in the boost namespace so the intrusive_ptr<> template
51 // finds the intrusive_ptr_add_ref() and intrusive_ptr_release() functions
52 // whatever the compiler. (see the boost::intrusive_ptr documentation)
53 //
54 // http://www.boost.org/libs/smart_ptr/intrusive_ptr.html
55 //
56 namespace boost
57 {
58 
59 
60 
61 
62 // objects are derived last from this class; this way they
63 // can be reference counted
65 {
66 public:
67  intrusive_ptr_object() throw()
68  : m_ref_count(0)
69  {
70  }
71  virtual ~intrusive_ptr_object() = 0;
72 
73  void add_ref() const
74  {
75 #if defined(BOOST_HAS_THREADS)
76  mutex::scoped_lock lock(m_mutex);
77 #endif
78  ++m_ref_count;
79  }
80  void release() const
81  {
82 #if defined(BOOST_HAS_THREADS)
83  mutex::scoped_lock lock(m_mutex);
84 #endif
85  // since users should not call release() themselves but use
86  // the intrusive_ptr<> template instead, this should never happen
87  BOOST_ASSERT(m_ref_count != 0);
88  --m_ref_count;
89  if(m_ref_count == 0) {
90  delete this;
91  }
92  }
93 
94 private:
95  mutable unsigned int m_ref_count;
96 #if defined(BOOST_HAS_THREADS)
97  mutable mutex m_mutex;
98 #endif
99 };
100 
101 
102 inline intrusive_ptr_object::~intrusive_ptr_object()
103 {
104  // a stack object will be deleted without a release() call...
105  // if you use objects properly, this should never happen!
106  BOOST_ASSERT(m_ref_count == 0);
107 }
108 
109 
110 
111 // All your classes derive from this class to allow for the
112 // kqp::our_dynamic_cast<> in the intrusive_ptr_add_ref() and
113 // intrusive_ptr_release() functions.
115 {
116 public:
117  // cannot instantiate
118  virtual ~intrusive_ptr_base() = 0;
119 };
120 
121 inline intrusive_ptr_base::~intrusive_ptr_base()
122 {
123 }
124 
125 
126 inline void intrusive_ptr_add_ref(const intrusive_ptr_base *a)
127 {
128  kqp::our_dynamic_cast<const intrusive_ptr_object *>(a)->add_ref();
129 }
130 
131 
132 inline void intrusive_ptr_release(const intrusive_ptr_base *a)
133 {
134  kqp::our_dynamic_cast<const intrusive_ptr_object *>(a)->release();
135 }
136 
137 
138 
139 // the classes you want to allocate with new and manage with
140 // an intrusive_ptr<> template are typedef with this template
141 // first, i.e.
142 //
143 // class A;
144 // typedef intrusive_ptr_heap<A> A_heap;
145 //
146 template<class T> class intrusive_ptr_heap : public T, public intrusive_ptr_object {};
147 
148 } // namespace boost
149 
150 
151 #endif // #ifdef BOOST_INTRUSIVE_PTR_OBJECT
152 // vim: ts=4