]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/shared_count.hpp
update to boost 1.30.1
[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 defined(_MSC_VER) && (_MSC_VER >= 1020)
5 # pragma once
6 #endif
7
8 //
9 //  detail/shared_count.hpp
10 //
11 //  Copyright (c) 2001, 2002, 2003 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 #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
22 # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
23 #endif
24
25 #include <boost/checked_delete.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/detail/lightweight_mutex.hpp>
28
29 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
30 #include <boost/detail/quick_allocator.hpp>
31 #endif
32
33 #include <memory>           // std::auto_ptr, std::allocator
34 #include <functional>       // std::less
35 #include <exception>        // std::exception
36 #include <new>              // std::bad_alloc
37 #include <typeinfo>         // std::type_info in get_deleter
38 #include <cstddef>          // std::size_t
39
40 #ifdef __BORLANDC__
41 # pragma warn -8026     // Functions with excep. spec. are not expanded inline
42 # pragma warn -8027     // Functions containing try are not expanded inline
43 #endif
44
45 namespace boost
46 {
47
48 // Debug hooks
49
50 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
51
52 void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
53 void sp_array_constructor_hook(void * px);
54 void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
55 void sp_array_destructor_hook(void * px);
56
57 #endif
58
59
60 // The standard library that comes with Borland C++ 5.5.1
61 // defines std::exception and its members as having C calling
62 // convention (-pc). When the definition of bad_weak_ptr
63 // is compiled with -ps, the compiler issues an error.
64 // Hence, the temporary #pragma option -pc below. The version
65 // check is deliberately conservative.
66
67 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
68 # pragma option push -pc
69 #endif
70
71 class bad_weak_ptr: public std::exception
72 {
73 public:
74
75     virtual char const * what() const throw()
76     {
77         return "boost::bad_weak_ptr";
78     }
79 };
80
81 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
82 # pragma option pop
83 #endif
84
85 namespace detail
86 {
87
88 class sp_counted_base
89 {
90 private:
91
92     typedef detail::lightweight_mutex mutex_type;
93
94 public:
95
96     sp_counted_base(): use_count_(1), weak_count_(1)
97     {
98     }
99
100     virtual ~sp_counted_base() // nothrow
101     {
102     }
103
104     // dispose() is called when use_count_ drops to zero, to release
105     // the resources managed by *this.
106
107     virtual void dispose() = 0; // nothrow
108
109     // destruct() is called when weak_count_ drops to zero.
110
111     virtual void destruct() // nothrow
112     {
113         delete this;
114     }
115
116     virtual void * get_deleter(std::type_info const & ti) = 0;
117
118     void add_ref()
119     {
120 #if defined(BOOST_HAS_THREADS)
121         mutex_type::scoped_lock lock(mtx_);
122 #endif
123         if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::bad_weak_ptr());
124         ++use_count_;
125         ++weak_count_;
126     }
127
128     void release() // nothrow
129     {
130         {
131 #if defined(BOOST_HAS_THREADS)
132             mutex_type::scoped_lock lock(mtx_);
133 #endif
134             long new_use_count = --use_count_;
135
136             if(new_use_count != 0)
137             {
138                 --weak_count_;
139                 return;
140             }
141         }
142
143         dispose();
144         weak_release();
145     }
146
147     void weak_add_ref() // nothrow
148     {
149 #if defined(BOOST_HAS_THREADS)
150         mutex_type::scoped_lock lock(mtx_);
151 #endif
152         ++weak_count_;
153     }
154
155     void weak_release() // nothrow
156     {
157         long new_weak_count;
158
159         {
160 #if defined(BOOST_HAS_THREADS)
161             mutex_type::scoped_lock lock(mtx_);
162 #endif
163             new_weak_count = --weak_count_;
164         }
165
166         if(new_weak_count == 0)
167         {
168             destruct();
169         }
170     }
171
172     long use_count() const // nothrow
173     {
174 #if defined(BOOST_HAS_THREADS)
175         mutex_type::scoped_lock lock(mtx_);
176 #endif
177         return use_count_;
178     }
179
180 private:
181
182     sp_counted_base(sp_counted_base const &);
183     sp_counted_base & operator= (sp_counted_base const &);
184
185     // inv: use_count_ <= weak_count_
186
187     long use_count_;
188     long weak_count_;
189
190 #if defined(BOOST_HAS_THREADS)
191     mutable mutex_type mtx_;
192 #endif
193 };
194
195 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
196
197 template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
198 {
199     boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
200 }
201
202 template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
203 {
204     boost::sp_array_constructor_hook(px);
205 }
206
207 template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
208 {
209 }
210
211 template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
212 {
213     boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
214 }
215
216 template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
217 {
218     boost::sp_array_destructor_hook(px);
219 }
220
221 template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
222 {
223 }
224
225 #endif
226
227 //
228 // Borland's Codeguard trips up over the -Vx- option here:
229 //
230 #ifdef __CODEGUARD__
231 # pragma option push -Vx-
232 #endif
233
234 template<class P, class D> class sp_counted_base_impl: public sp_counted_base
235 {
236 private:
237
238     P ptr; // copy constructor must not throw
239     D del; // copy constructor must not throw
240
241     sp_counted_base_impl(sp_counted_base_impl const &);
242     sp_counted_base_impl & operator= (sp_counted_base_impl const &);
243
244     typedef sp_counted_base_impl<P, D> this_type;
245
246 public:
247
248     // pre: initial_use_count <= initial_weak_count, d(p) must not throw
249
250     sp_counted_base_impl(P p, D d): ptr(p), del(d)
251     {
252 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
253         detail::cbi_call_constructor_hook(this, p, d, 0);
254 #endif
255     }
256
257     virtual void dispose() // nothrow
258     {
259 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
260         detail::cbi_call_destructor_hook(this, ptr, del, 0);
261 #endif
262         del(ptr);
263     }
264
265     virtual void * get_deleter(std::type_info const & ti)
266     {
267         return ti == typeid(D)? &del: 0;
268     }
269
270 #if defined(BOOST_SP_USE_STD_ALLOCATOR)
271
272     void * operator new(std::size_t)
273     {
274         return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
275     }
276
277     void operator delete(void * p)
278     {
279         std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
280     }
281
282 #endif
283
284 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
285
286     void * operator new(std::size_t)
287     {
288         return quick_allocator<this_type>::alloc();
289     }
290
291     void operator delete(void * p)
292     {
293         quick_allocator<this_type>::dealloc(p);
294     }
295
296 #endif
297 };
298
299 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
300
301 int const shared_count_id = 0x2C35F101;
302 int const   weak_count_id = 0x298C38A4;
303
304 #endif
305
306 class weak_count;
307
308 class shared_count
309 {
310 private:
311
312     sp_counted_base * pi_;
313
314 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
315     int id_;
316 #endif
317
318     friend class weak_count;
319
320 public:
321
322     shared_count(): pi_(0) // nothrow
323 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
324         , id_(shared_count_id)
325 #endif
326     {
327     }
328
329     template<class P, class D> shared_count(P p, D d): pi_(0)
330 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
331         , id_(shared_count_id)
332 #endif
333     {
334 #ifndef BOOST_NO_EXCEPTIONS
335
336         try
337         {
338             pi_ = new sp_counted_base_impl<P, D>(p, d);
339         }
340         catch(...)
341         {
342             d(p); // delete p
343             throw;
344         }
345
346 #else
347
348         pi_ = new sp_counted_base_impl<P, D>(p, d);
349
350         if(pi_ == 0)
351         {
352             d(p); // delete p
353             boost::throw_exception(std::bad_alloc());
354         }
355
356 #endif
357     }
358
359 #ifndef BOOST_NO_AUTO_PTR
360
361     // auto_ptr<Y> is special cased to provide the strong guarantee
362
363     template<class Y>
364     explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>()))
365 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
366         , id_(shared_count_id)
367 #endif
368     {
369         r.release();
370     }
371
372 #endif 
373
374     ~shared_count() // nothrow
375     {
376         if(pi_ != 0) pi_->release();
377 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
378         id_ = 0;
379 #endif
380     }
381
382     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
383 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
384         , id_(shared_count_id)
385 #endif
386     {
387         if(pi_ != 0) pi_->add_ref();
388     }
389
390     explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
391
392     shared_count & operator= (shared_count const & r) // nothrow
393     {
394         sp_counted_base * tmp = r.pi_;
395         if(tmp != 0) tmp->add_ref();
396         if(pi_ != 0) pi_->release();
397         pi_ = tmp;
398
399         return *this;
400     }
401
402     void swap(shared_count & r) // nothrow
403     {
404         sp_counted_base * tmp = r.pi_;
405         r.pi_ = pi_;
406         pi_ = tmp;
407     }
408
409     long use_count() const // nothrow
410     {
411         return pi_ != 0? pi_->use_count(): 0;
412     }
413
414     bool unique() const // nothrow
415     {
416         return use_count() == 1;
417     }
418
419     friend inline bool operator==(shared_count const & a, shared_count const & b)
420     {
421         return a.pi_ == b.pi_;
422     }
423
424     friend inline bool operator<(shared_count const & a, shared_count const & b)
425     {
426         return std::less<sp_counted_base *>()(a.pi_, b.pi_);
427     }
428
429     void * get_deleter(std::type_info const & ti) const
430     {
431         return pi_? pi_->get_deleter(ti): 0;
432     }
433 };
434
435 #ifdef __CODEGUARD__
436 # pragma option pop
437 #endif
438
439
440 class weak_count
441 {
442 private:
443
444     sp_counted_base * pi_;
445
446 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
447     int id_;
448 #endif
449
450     friend class shared_count;
451
452 public:
453
454     weak_count(): pi_(0) // nothrow
455 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
456         , id_(weak_count_id)
457 #endif
458     {
459     }
460
461     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
462 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
463         , id_(shared_count_id)
464 #endif
465     {
466         if(pi_ != 0) pi_->weak_add_ref();
467     }
468
469     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
470 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
471         , id_(shared_count_id)
472 #endif
473     {
474         if(pi_ != 0) pi_->weak_add_ref();
475     }
476
477     ~weak_count() // nothrow
478     {
479         if(pi_ != 0) pi_->weak_release();
480 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
481         id_ = 0;
482 #endif
483     }
484
485     weak_count & operator= (shared_count const & r) // nothrow
486     {
487         sp_counted_base * tmp = r.pi_;
488         if(tmp != 0) tmp->weak_add_ref();
489         if(pi_ != 0) pi_->weak_release();
490         pi_ = tmp;
491
492         return *this;
493     }
494
495     weak_count & operator= (weak_count const & r) // nothrow
496     {
497         sp_counted_base * tmp = r.pi_;
498         if(tmp != 0) tmp->weak_add_ref();
499         if(pi_ != 0) pi_->weak_release();
500         pi_ = tmp;
501
502         return *this;
503     }
504
505     void swap(weak_count & r) // nothrow
506     {
507         sp_counted_base * tmp = r.pi_;
508         r.pi_ = pi_;
509         pi_ = tmp;
510     }
511
512     long use_count() const // nothrow
513     {
514         return pi_ != 0? pi_->use_count(): 0;
515     }
516
517     friend inline bool operator==(weak_count const & a, weak_count const & b)
518     {
519         return a.pi_ == b.pi_;
520     }
521
522     friend inline bool operator<(weak_count const & a, weak_count const & b)
523     {
524         return std::less<sp_counted_base *>()(a.pi_, b.pi_);
525     }
526 };
527
528 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
529 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
530         , id_(shared_count_id)
531 #endif
532 {
533     if(pi_ != 0)
534     {
535         pi_->add_ref();
536     }
537     else
538     {
539         boost::throw_exception(boost::bad_weak_ptr());
540     }
541 }
542
543 } // namespace detail
544
545 } // namespace boost
546
547 #ifdef __BORLANDC__
548 # pragma warn .8027     // Functions containing try are not expanded inline
549 # pragma warn .8026     // Functions with excep. spec. are not expanded inline
550 #endif
551
552 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED