]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/shared_count.hpp
major boost update
[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         if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
87         ++use_count_;
88         ++weak_count_;
89     }
90
91     void release() // nothrow
92     {
93         long new_use_count;
94         long new_weak_count;
95
96         {
97 #ifdef BOOST_HAS_THREADS
98             mutex_type::scoped_lock lock(mtx_);
99 #endif
100             new_use_count = --use_count_;
101             new_weak_count = --weak_count_;
102         }
103
104         if(new_use_count == 0)
105         {
106             dispose();
107         }
108
109         if(new_weak_count == 0)
110         {
111             // not a direct 'delete this', because the inlined
112             // release() may use a different heap manager
113             self_deleter_(this);
114         }
115     }
116
117     void weak_add_ref() // nothrow
118     {
119 #ifdef BOOST_HAS_THREADS
120         mutex_type::scoped_lock lock(mtx_);
121 #endif
122         ++weak_count_;
123     }
124
125     void weak_release() // nothrow
126     {
127         long new_weak_count;
128
129         {
130 #ifdef BOOST_HAS_THREADS
131             mutex_type::scoped_lock lock(mtx_);
132 #endif
133             new_weak_count = --weak_count_;
134         }
135
136         if(new_weak_count == 0)
137         {
138             self_deleter_(this);
139         }
140     }
141
142     long use_count() const // nothrow
143     {
144 #ifdef BOOST_HAS_THREADS
145         mutex_type::scoped_lock lock(mtx_);
146 #endif
147         return use_count_;
148     }
149
150 private:
151
152     counted_base(counted_base const &);
153     counted_base & operator= (counted_base const &);
154
155     static void self_delete(counted_base * p)
156     {
157         delete p;
158     }
159
160     // inv: use_count_ <= weak_count_
161
162     long use_count_;
163     long weak_count_;
164 #ifdef BOOST_HAS_THREADS
165     mutable mutex_type mtx_;
166 #endif
167     void (*self_deleter_) (counted_base *);
168 };
169
170 inline void intrusive_ptr_add_ref(counted_base * p)
171 {
172     p->add_ref();
173 }
174
175 inline void intrusive_ptr_release(counted_base * p)
176 {
177     p->release();
178 }
179
180 namespace detail
181 {
182
183 template<class P, class D> class counted_base_impl: public counted_base
184 {
185 private:
186
187     P ptr; // copy constructor must not throw
188     D del; // copy constructor must not throw
189
190     counted_base_impl(counted_base_impl const &);
191     counted_base_impl & operator= (counted_base_impl const &);
192
193 public:
194
195     // pre: initial_use_count <= initial_weak_count, d(p) must not throw
196
197     counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
198         counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
199     {
200     }
201
202     virtual void dispose() // nothrow
203     {
204         del(ptr);
205     }
206 };
207
208 class weak_count;
209
210 class shared_count
211 {
212 private:
213
214     counted_base * pi_;
215
216     friend class weak_count;
217
218     template<class P, class D> shared_count(P, D, counted_base const *);
219
220 public:
221
222     shared_count(): pi_(new counted_base(1, 1))
223     {
224     }
225
226     explicit shared_count(counted_base * pi): pi_(pi) // never throws
227     {
228         pi_->add_ref();
229     }
230
231     template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
232     {
233         try
234         {
235             pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
236         }
237         catch(...)
238         {
239             d(p); // delete p
240             throw;
241         }
242     }
243
244     template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
245     {
246         pi_->add_ref();
247     }
248
249 #ifndef BOOST_NO_AUTO_PTR
250
251     // auto_ptr<Y> is special cased to provide the strong guarantee
252
253     template<typename Y>
254     explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
255     {
256         r.release();
257     }
258
259 #endif 
260
261     ~shared_count() // nothrow
262     {
263         pi_->release();
264     }
265
266     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
267     {
268         pi_->add_ref();
269     }
270
271     explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
272
273     shared_count & operator= (shared_count const & r) // nothrow
274     {
275         counted_base * tmp = r.pi_;
276         tmp->add_ref();
277         pi_->release();
278         pi_ = tmp;
279
280         return *this;
281     }
282
283     void swap(shared_count & r) // nothrow
284     {
285         counted_base * tmp = r.pi_;
286         r.pi_ = pi_;
287         pi_ = tmp;
288     }
289
290     long use_count() const // nothrow
291     {
292         return pi_->use_count();
293     }
294
295     bool unique() const // nothrow
296     {
297         return pi_->use_count() == 1;
298     }
299
300     friend inline bool operator==(shared_count const & a, shared_count const & b)
301     {
302         return a.pi_ == b.pi_;
303     }
304
305     friend inline bool operator<(shared_count const & a, shared_count const & b)
306     {
307         return std::less<counted_base *>()(a.pi_, b.pi_);
308     }
309 };
310
311 class weak_count
312 {
313 private:
314
315     counted_base * pi_;
316
317     friend class shared_count;
318
319 public:
320
321     weak_count(): pi_(new counted_base(0, 1)) // can throw
322     {
323     }
324
325     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
326     {
327         pi_->weak_add_ref();
328     }
329
330     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
331     {
332         pi_->weak_add_ref();
333     }
334
335     ~weak_count() // nothrow
336     {
337         pi_->weak_release();
338     }
339
340     weak_count & operator= (shared_count const & r) // nothrow
341     {
342         counted_base * tmp = r.pi_;
343         tmp->weak_add_ref();
344         pi_->weak_release();
345         pi_ = tmp;
346
347         return *this;
348     }
349
350     weak_count & operator= (weak_count const & r) // nothrow
351     {
352         counted_base * tmp = r.pi_;
353         tmp->weak_add_ref();
354         pi_->weak_release();
355         pi_ = tmp;
356
357         return *this;
358     }
359
360     void swap(weak_count & r) // nothrow
361     {
362         counted_base * tmp = r.pi_;
363         r.pi_ = pi_;
364         pi_ = tmp;
365     }
366
367     long use_count() const // nothrow
368     {
369         return pi_->use_count();
370     }
371
372     friend inline bool operator==(weak_count const & a, weak_count const & b)
373     {
374         return a.pi_ == b.pi_;
375     }
376
377     friend inline bool operator<(weak_count const & a, weak_count const & b)
378     {
379         return std::less<counted_base *>()(a.pi_, b.pi_);
380     }
381 };
382
383 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
384 {
385     pi_->add_ref();
386 }
387
388 } // namespace detail
389
390 } // namespace boost
391
392 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED