~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to boost/boost/detail/shared_count.hpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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