]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/shared_count.hpp
make boost compile without exceptions
[lyx.git] / boost / boost / detail / shared_count.hpp
1 #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
2 #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
3
4 #if _MSC_VER >= 1020
5 #pragma once
6 #endif
7
8 //
9 //  detail/shared_count.hpp
10 //
11 //  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
12 //
13 //  Permission to copy, use, modify, sell and distribute this software
14 //  is granted provided this copyright notice appears in all copies.
15 //  This software is provided "as is" without express or implied
16 //  warranty, and with no claim as to its suitability for any purpose.
17 //
18
19 #include <boost/config.hpp>
20
21 #ifndef BOOST_NO_AUTO_PTR
22 # include <memory>
23 #endif
24
25 #include <boost/checked_delete.hpp>
26 #include <boost/detail/lightweight_mutex.hpp>
27
28 #include <functional>       // for std::less
29 #include <exception>        // for std::exception
30
31 namespace boost
32 {
33
34 class use_count_is_zero: public std::exception
35 {
36 public:
37
38     virtual char const * what() const throw()
39     {
40         return "use_count_is_zero";
41     }
42 };
43
44 class counted_base
45 {
46 private:
47
48     typedef detail::lightweight_mutex mutex_type;
49
50 public:
51
52     counted_base():
53         use_count_(0), weak_count_(0), self_deleter_(&self_delete)
54     {
55     }
56
57     // pre: initial_use_count <= initial_weak_count
58
59     explicit counted_base(long initial_use_count, long initial_weak_count):
60         use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
61     {
62     }
63
64     virtual ~counted_base() // nothrow
65     {
66     }
67
68     // dispose() is called when use_count_ drops to zero, to release
69     // the resources managed by *this.
70     //
71     // counted_base doesn't manage any resources except itself, and
72     // the default implementation is a no-op.
73     //
74     // dispose() is not pure virtual since weak_ptr instantiates a
75     // counted_base in its default constructor.
76
77     virtual void dispose() // nothrow
78     {
79     }
80
81     void add_ref()
82     {
83 #ifdef BOOST_HAS_THREADS
84         mutex_type::scoped_lock lock(mtx_);
85 #endif
86 #ifndef BOOST_NO_EXCEPTIONS
87         if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
88 #endif
89         BOOST_NOEH_ASSERT(!(use_count_ == 0 && weak_count_ != 0));
90         ++use_count_;
91         ++weak_count_;
92     }
93
94     void release() // nothrow
95     {
96         long new_use_count;
97         long new_weak_count;
98
99         {
100 #ifdef BOOST_HAS_THREADS
101             mutex_type::scoped_lock lock(mtx_);
102 #endif
103             new_use_count = --use_count_;
104             new_weak_count = --weak_count_;
105         }
106
107         if(new_use_count == 0)
108         {
109             dispose();
110         }
111
112         if(new_weak_count == 0)
113         {
114             // not a direct 'delete this', because the inlined
115             // release() may use a different heap manager
116             self_deleter_(this);
117         }
118     }
119
120     void weak_add_ref() // nothrow
121     {
122 #ifdef BOOST_HAS_THREADS
123         mutex_type::scoped_lock lock(mtx_);
124 #endif
125         ++weak_count_;
126     }
127
128     void weak_release() // nothrow
129     {
130         long new_weak_count;
131
132         {
133 #ifdef BOOST_HAS_THREADS
134             mutex_type::scoped_lock lock(mtx_);
135 #endif
136             new_weak_count = --weak_count_;
137         }
138
139         if(new_weak_count == 0)
140         {
141             self_deleter_(this);
142         }
143     }
144
145     long use_count() const // nothrow
146     {
147 #ifdef BOOST_HAS_THREADS
148         mutex_type::scoped_lock lock(mtx_);
149 #endif
150         return use_count_;
151     }
152
153 private:
154
155     counted_base(counted_base const &);
156     counted_base & operator= (counted_base const &);
157
158     static void self_delete(counted_base * p)
159     {
160         delete p;
161     }
162
163     // inv: use_count_ <= weak_count_
164
165     long use_count_;
166     long weak_count_;
167 #ifdef BOOST_HAS_THREADS
168     mutable mutex_type mtx_;
169 #endif
170     void (*self_deleter_) (counted_base *);
171 };
172
173 inline void intrusive_ptr_add_ref(counted_base * p)
174 {
175     p->add_ref();
176 }
177
178 inline void intrusive_ptr_release(counted_base * p)
179 {
180     p->release();
181 }
182
183 namespace detail
184 {
185
186 template<class P, class D> class counted_base_impl: public counted_base
187 {
188 private:
189
190     P ptr; // copy constructor must not throw
191     D del; // copy constructor must not throw
192
193     counted_base_impl(counted_base_impl const &);
194     counted_base_impl & operator= (counted_base_impl const &);
195
196 public:
197
198     // pre: initial_use_count <= initial_weak_count, d(p) must not throw
199
200     counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
201         counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
202     {
203     }
204
205     virtual void dispose() // nothrow
206     {
207         del(ptr);
208     }
209 };
210
211 class weak_count;
212
213 class shared_count
214 {
215 private:
216
217     counted_base * pi_;
218
219     friend class weak_count;
220
221     template<class P, class D> shared_count(P, D, counted_base const *);
222
223 public:
224
225     shared_count(): pi_(new counted_base(1, 1))
226     {
227     }
228
229     explicit shared_count(counted_base * pi): pi_(pi) // never throws
230     {
231         pi_->add_ref();
232     }
233
234     template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
235     {
236         try
237         {
238             pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
239         }
240         catch(...)
241         {
242             d(p); // delete p
243 #ifndef BOOST_NO_EXCEPTIONS
244             throw;
245 #endif
246             BOOST_NOEH_ASSERT(false);
247         }
248     }
249
250     template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
251     {
252         pi_->add_ref();
253     }
254
255 #ifndef BOOST_NO_AUTO_PTR
256
257     // auto_ptr<Y> is special cased to provide the strong guarantee
258
259     template<typename Y>
260     explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
261     {
262         r.release();
263     }
264
265 #endif
266
267     ~shared_count() // nothrow
268     {
269         pi_->release();
270     }
271
272     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
273     {
274         pi_->add_ref();
275     }
276
277     explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
278
279     shared_count & operator= (shared_count const & r) // nothrow
280     {
281         counted_base * tmp = r.pi_;
282         tmp->add_ref();
283         pi_->release();
284         pi_ = tmp;
285
286         return *this;
287     }
288
289     void swap(shared_count & r) // nothrow
290     {
291         counted_base * tmp = r.pi_;
292         r.pi_ = pi_;
293         pi_ = tmp;
294     }
295
296     long use_count() const // nothrow
297     {
298         return pi_->use_count();
299     }
300
301     bool unique() const // nothrow
302     {
303         return pi_->use_count() == 1;
304     }
305
306     friend inline bool operator==(shared_count const & a, shared_count const & b)
307     {
308         return a.pi_ == b.pi_;
309     }
310
311     friend inline bool operator<(shared_count const & a, shared_count const & b)
312     {
313         return std::less<counted_base *>()(a.pi_, b.pi_);
314     }
315 };
316
317 class weak_count
318 {
319 private:
320
321     counted_base * pi_;
322
323     friend class shared_count;
324
325 public:
326
327     weak_count(): pi_(new counted_base(0, 1)) // can throw
328     {
329     }
330
331     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
332     {
333         pi_->weak_add_ref();
334     }
335
336     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
337     {
338         pi_->weak_add_ref();
339     }
340
341     ~weak_count() // nothrow
342     {
343         pi_->weak_release();
344     }
345
346     weak_count & operator= (shared_count const & r) // nothrow
347     {
348         counted_base * tmp = r.pi_;
349         tmp->weak_add_ref();
350         pi_->weak_release();
351         pi_ = tmp;
352
353         return *this;
354     }
355
356     weak_count & operator= (weak_count const & r) // nothrow
357     {
358         counted_base * tmp = r.pi_;
359         tmp->weak_add_ref();
360         pi_->weak_release();
361         pi_ = tmp;
362
363         return *this;
364     }
365
366     void swap(weak_count & r) // nothrow
367     {
368         counted_base * tmp = r.pi_;
369         r.pi_ = pi_;
370         pi_ = tmp;
371     }
372
373     long use_count() const // nothrow
374     {
375         return pi_->use_count();
376     }
377
378     friend inline bool operator==(weak_count const & a, weak_count const & b)
379     {
380         return a.pi_ == b.pi_;
381     }
382
383     friend inline bool operator<(weak_count const & a, weak_count const & b)
384     {
385         return std::less<counted_base *>()(a.pi_, b.pi_);
386     }
387 };
388
389 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
390 {
391     pi_->add_ref();
392 }
393
394 } // namespace detail
395
396 } // namespace boost
397
398 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED