]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/shared_count.hpp
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 #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 #ifndef BOOST_NO_EXCEPTIONS
237         try
238         {
239 #endif
240             pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
241 #ifndef BOOST_NO_EXCEPTIONS
242         }
243 #endif
244 #ifndef BOOST_NO_EXCEPTIONS
245         catch(...)
246                 
247         {
248             d(p); // delete p
249             throw;
250         }
251 #endif
252         BOOST_NOEH_ASSERT(pi_);
253     }
254
255     template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
256     {
257         pi_->add_ref();
258     }
259
260 #ifndef BOOST_NO_AUTO_PTR
261
262     // auto_ptr<Y> is special cased to provide the strong guarantee
263
264     template<typename Y>
265     explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
266     {
267         r.release();
268     }
269
270 #endif
271
272     ~shared_count() // nothrow
273     {
274         pi_->release();
275     }
276
277     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
278     {
279         pi_->add_ref();
280     }
281
282     explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
283
284     shared_count & operator= (shared_count const & r) // nothrow
285     {
286         counted_base * tmp = r.pi_;
287         tmp->add_ref();
288         pi_->release();
289         pi_ = tmp;
290
291         return *this;
292     }
293
294     void swap(shared_count & r) // nothrow
295     {
296         counted_base * tmp = r.pi_;
297         r.pi_ = pi_;
298         pi_ = tmp;
299     }
300
301     long use_count() const // nothrow
302     {
303         return pi_->use_count();
304     }
305
306     bool unique() const // nothrow
307     {
308         return pi_->use_count() == 1;
309     }
310
311     friend inline bool operator==(shared_count const & a, shared_count const & b)
312     {
313         return a.pi_ == b.pi_;
314     }
315
316     friend inline bool operator<(shared_count const & a, shared_count const & b)
317     {
318         return std::less<counted_base *>()(a.pi_, b.pi_);
319     }
320 };
321
322 class weak_count
323 {
324 private:
325
326     counted_base * pi_;
327
328     friend class shared_count;
329
330 public:
331
332     weak_count(): pi_(new counted_base(0, 1)) // can throw
333     {
334     }
335
336     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
337     {
338         pi_->weak_add_ref();
339     }
340
341     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
342     {
343         pi_->weak_add_ref();
344     }
345
346     ~weak_count() // nothrow
347     {
348         pi_->weak_release();
349     }
350
351     weak_count & operator= (shared_count const & r) // nothrow
352     {
353         counted_base * tmp = r.pi_;
354         tmp->weak_add_ref();
355         pi_->weak_release();
356         pi_ = tmp;
357
358         return *this;
359     }
360
361     weak_count & operator= (weak_count const & r) // nothrow
362     {
363         counted_base * tmp = r.pi_;
364         tmp->weak_add_ref();
365         pi_->weak_release();
366         pi_ = tmp;
367
368         return *this;
369     }
370
371     void swap(weak_count & r) // nothrow
372     {
373         counted_base * tmp = r.pi_;
374         r.pi_ = pi_;
375         pi_ = tmp;
376     }
377
378     long use_count() const // nothrow
379     {
380         return pi_->use_count();
381     }
382
383     friend inline bool operator==(weak_count const & a, weak_count const & b)
384     {
385         return a.pi_ == b.pi_;
386     }
387
388     friend inline bool operator<(weak_count const & a, weak_count const & b)
389     {
390         return std::less<counted_base *>()(a.pi_, b.pi_);
391     }
392 };
393
394 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
395 {
396     pi_->add_ref();
397 }
398
399 } // namespace detail
400
401 } // namespace boost
402
403 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED