1 // Baruch Even baruch@ev-en.org 2001-02-20
2 // This version is a modified version for use in LyX
3 // The modifications are done in order to use it where exceptions are disabled
4 // Currently it has no "no memory" checks in place, asserts are probably the
6 // all changed are #ifded'ed by LYX_NO_EXCEPTIONS
7 #define LYX_NO_EXCEPTIONS
9 // Boost smart_ptr.hpp header file -----------------------------------------//
11 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
12 // use, modify, sell and distribute this software is granted provided this
13 // copyright notice appears in all copies. This software is provided "as is"
14 // without express or implied warranty, and with no claim as to its
15 // suitability for any purpose.
17 // See http://www.boost.org for most recent version including documentation.
20 // 21 May 01 Require complete type where incomplete type is unsafe.
21 // (suggested by Vladimir Prus)
22 // 21 May 01 operator= fails if operand transitively owned by *this, as in a
23 // linked list (report by Ken Johnson, fix by Beman Dawes)
24 // 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams)
25 // 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
26 // 24 Jul 00 Change throw() to // never throws. See lib guidelines
27 // Exception-specification rationale. (Beman Dawes)
28 // 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
29 // 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
31 // 31 Dec 99 Condition tightened for no member template friend workaround
33 // 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
35 // 30 Nov 99 added operator ==, operator !=, and std::swap and std::less
36 // specializations for shared types (Darin Adler)
37 // 11 Oct 99 replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
38 // Bonnard), added shared_ptr workaround for no member template
39 // friends (Matthew Langston)
40 // 25 Sep 99 added shared_ptr::swap and shared_array::swap (Luis Coelho).
41 // 20 Jul 99 changed name to smart_ptr.hpp, #include <boost/config.hpp>,
42 // #include <boost/utility.hpp> and use boost::noncopyable
43 // 17 May 99 remove scoped_array and shared_array operator*() as
44 // unnecessary (Beman Dawes)
45 // 14 May 99 reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
46 // 13 May 99 remove certain throw() specifiers to avoid generated try/catch
47 // code cost (Beman Dawes)
48 // 11 May 99 get() added, conversion to T* placed in macro guard (Valentin
49 // Bonnard, Dave Abrahams, and others argued for elimination
50 // of the automatic conversion)
51 // 28 Apr 99 #include <memory> fix (Valentin Bonnard)
52 // 28 Apr 99 rename transfer() to share() for clarity (Dave Abrahams)
53 // 28 Apr 99 remove unsafe shared_array template conversions(Valentin Bonnard)
54 // 28 Apr 99 p(r) changed to p(r.px) for clarity (Dave Abrahams)
55 // 21 Apr 99 reset() self assignment fix (Valentin Bonnard)
56 // 21 Apr 99 dispose() provided to improve clarity (Valentin Bonnard)
57 // 27 Apr 99 leak when new throws fixes (Dave Abrahams)
58 // 21 Oct 98 initial Version (Greg Colvin/Beman Dawes)
60 #ifndef LYX_SMART_PTR_H
61 #define LYX_SMART_PTR_H
63 #include <boost/config.hpp> // for broken compiler workarounds
64 #include <cstddef> // for std::size_t
65 #include <memory> // for std::auto_ptr
66 #include <algorithm> // for std::swap
67 #include "support/utility.h" // for boost::noncopyable, checked_delete, checked_array_delete
68 #include <functional> // for std::less
69 #include <boost/static_assert.hpp> // for BOOST_STATIC_ASSERT
71 #ifdef LYX_NO_EXCEPTIONS
77 // shared_ptr --------------------------------------------------------------//
79 // An enhanced relative of scoped_ptr with reference counted copy semantics.
80 // The object pointed to is deleted when the last shared_ptr pointing to it
81 // is destroyed or reset.
83 template<typename T> class shared_c_ptr {
85 typedef T element_type;
87 explicit shared_c_ptr(T* p =0) : px(p) {
88 #ifndef LYX_NO_EXCEPTIONS
89 try { pn = new long(1); } // fix: prevent leak if new throws
90 catch (...) { checked_delete(p); throw; }
97 shared_c_ptr(const shared_c_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
99 ~shared_c_ptr() { dispose(); }
101 shared_c_ptr& operator=(const shared_c_ptr& r) {
106 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
108 shared_c_ptr(const shared_c_ptr<Y>& r) : px(r.px) { // never throws
111 #ifndef BOOST_NO_AUTO_PTR
113 explicit shared_c_ptr(std::auto_ptr<Y>& r) {
114 pn = new long(1); // may throw
115 px = r.release(); // fix: moved here to stop leak if new throws
120 shared_c_ptr& operator=(const shared_c_ptr<Y>& r) {
125 #ifndef BOOST_NO_AUTO_PTR
127 shared_c_ptr& operator=(std::auto_ptr<Y>& r) {
128 // code choice driven by guarantee of "no effect if new throws"
129 if (*pn == 1) { checked_delete(px); }
130 else { // allocate new reference counter
131 long * tmp = new long(1); // may throw
132 --*pn; // only decrement once danger of new throwing is past
134 } // allocate new reference counter
135 px = r.release(); // fix: moved here so doesn't leak if new throws
140 #ifndef BOOST_NO_AUTO_PTR
141 explicit shared_c_ptr(std::auto_ptr<T>& r) {
142 pn = new long(1); // may throw
143 px = r.release(); // fix: moved here to stop leak if new throws
146 shared_c_ptr& operator=(std::auto_ptr<T>& r) {
147 // code choice driven by guarantee of "no effect if new throws"
148 if (*pn == 1) { checked_delete(px); }
149 else { // allocate new reference counter
150 long * tmp = new long(1); // may throw
151 --*pn; // only decrement once danger of new throwing is past
153 } // allocate new reference counter
154 px = r.release(); // fix: moved here so doesn't leak if new throws
161 if (px == p) return; // fix: self-assignment safe
162 if (--*pn == 0) { checked_delete(px); }
163 else { // allocate new reference counter
164 #ifndef LYX_NO_EXCEPTIONS
165 try { pn = new long; } // fix: prevent leak if new throws
167 ++*pn; // undo effect of --*pn above to meet effects guarantee
175 } // allocate new reference counter
180 T& operator*() const { return *px; } // never throws
181 T* operator->() const { return px; } // never throws
182 T* get() const { return px; } // never throws
184 long use_count() const { return *pn; } // never throws
185 bool unique() const { return *pn == 1; } // never throws
187 void swap(shared_c_ptr<T>& other) // never throws
188 { std::swap(px,other.px); std::swap(pn,other.pn); }
190 // Tasteless as this may seem, making all members public allows member templates
191 // to work in the absence of member template friends. (Matthew Langston)
192 // Don't split this line into two; that causes problems for some GCC 2.95.2 builds
193 #if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
197 T* px; // contained pointer
198 long* pn; // ptr to reference counter
200 // Don't split this line into two; that causes problems for some GCC 2.95.2 builds
201 #if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
202 template<typename Y> friend class shared_ptr;
205 void dispose() { if (--*pn == 0) { checked_delete(px); delete pn; } }
207 void share(T* rpx, long* rpn) {
208 if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0
209 ++*rpn; // done before dispose() in case rpn transitively
210 // dependent on *this (bug reported by Ken Johnson)
218 template<typename T, typename U>
219 inline bool operator==(const shared_c_ptr<T>& a, const shared_c_ptr<U>& b)
220 { return a.get() == b.get(); }
222 template<typename T, typename U>
223 inline bool operator!=(const shared_c_ptr<T>& a, const shared_c_ptr<U>& b)
224 { return a.get() != b.get(); }
228 // specializations for things in namespace std -----------------------------//
230 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
234 // Specialize std::swap to use the fast, non-throwing swap that's provided
235 // as a member function instead of using the default algorithm which creates
236 // a temporary and uses assignment.
239 inline void swap(lyx::shared_c_ptr<T>& a, lyx::shared_c_ptr<T>& b)
242 // Specialize std::less so we can use shared pointers and arrays as keys in
243 // associative collections.
245 // It's still a controversial question whether this is better than supplying
246 // a full range of comparison operators (<, >, <=, >=).
249 struct less< lyx::shared_c_ptr<T> >
250 : binary_function<lyx::shared_c_ptr<T>, lyx::shared_c_ptr<T>, bool>
252 bool operator()(const lyx::shared_c_ptr<T>& a,
253 const lyx::shared_c_ptr<T>& b) const
254 { return less<T*>()(a.get(),b.get()); }
259 #endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
261 #endif // LYX_SMART_PTR_H