source: NonGTP/Boost/boost/serialization/detail/shared_count_132.hpp @ 857

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