]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/shared_count.hpp
a3707a1af8abc31e9b98f88ea4da407cb66b9664
[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 #ifdef __BORLANDC__
32 # pragma warn -8026     // Functions with excep. spec. are not expanded inline
33 # pragma warn -8027     // Functions containing try are not expanded inline
34 #endif
35
36 namespace boost
37 {
38
39 class use_count_is_zero: public std::exception
40 {
41 public:
42
43     virtual char const * what() const throw()
44     {
45         return "use_count_is_zero";
46     }
47 };
48
49 class counted_base
50 {
51 private:
52
53     typedef detail::lightweight_mutex mutex_type;
54
55 public:
56
57     counted_base():
58         use_count_(0), weak_count_(0)
59     {
60     }
61
62     // pre: initial_use_count <= initial_weak_count
63
64     explicit counted_base(long initial_use_count, long initial_weak_count):
65         use_count_(initial_use_count), weak_count_(initial_weak_count)
66     {
67     }
68
69     virtual ~counted_base() // nothrow
70     {
71     }
72
73     // dispose() is called when use_count_ drops to zero, to release
74     // the resources managed by *this.
75     //
76     // counted_base doesn't manage any resources except itself, and
77     // the default implementation is a no-op.
78     //
79     // dispose() is not pure virtual since weak_ptr instantiates a
80     // counted_base in its default constructor.
81
82     virtual void dispose() // nothrow
83     {
84     }
85
86     // destruct() is called when weak_count_ drops to zero.
87
88     virtual void destruct() // nothrow
89     {
90         delete this;
91     }
92
93     void add_ref()
94     {
95 #ifdef BOOST_HAS_THREADS
96         mutex_type::scoped_lock lock(mtx_);
97 #endif
98 #ifndef BOOST_NO_EXCEPTIONS
99         if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
100 #endif
101         BOOST_NOEH_ASSERT(!(use_count_ == 0 && weak_count_ != 0));
102         ++use_count_;
103         ++weak_count_;
104     }
105
106     void release() // nothrow
107     {
108         long new_use_count;
109         long new_weak_count;
110
111         {
112 #ifdef BOOST_HAS_THREADS
113             mutex_type::scoped_lock lock(mtx_);
114 #endif
115             new_use_count = --use_count_;
116             new_weak_count = --weak_count_;
117         }
118
119         if(new_use_count == 0)
120         {
121             dispose();
122         }
123
124         if(new_weak_count == 0)
125         {
126             destruct();
127         }
128     }
129
130     void weak_add_ref() // nothrow
131     {
132 #ifdef BOOST_HAS_THREADS
133         mutex_type::scoped_lock lock(mtx_);
134 #endif
135         ++weak_count_;
136     }
137
138     void weak_release() // nothrow
139     {
140         long new_weak_count;
141
142         {
143 #ifdef BOOST_HAS_THREADS
144             mutex_type::scoped_lock lock(mtx_);
145 #endif
146             new_weak_count = --weak_count_;
147         }
148
149         if(new_weak_count == 0)
150         {
151             destruct();
152         }
153     }
154
155     long use_count() const // nothrow
156     {
157 #ifdef BOOST_HAS_THREADS
158         mutex_type::scoped_lock lock(mtx_);
159 #endif
160         return use_count_;
161     }
162
163 private:
164
165     counted_base(counted_base const &);
166     counted_base & operator= (counted_base const &);
167
168     // inv: use_count_ <= weak_count_
169
170     long use_count_;
171     long weak_count_;
172
173 #ifdef BOOST_HAS_THREADS
174     mutable mutex_type mtx_;
175 #endif
176 };
177
178 inline void intrusive_ptr_add_ref(counted_base * p)
179 {
180     p->add_ref();
181 }
182
183 inline void intrusive_ptr_release(counted_base * p)
184 {
185     p->release();
186 }
187
188 namespace detail
189 {
190
191 template<class P, class D> class counted_base_impl: public counted_base
192 {
193 private:
194
195     P ptr; // copy constructor must not throw
196     D del; // copy constructor must not throw
197
198     counted_base_impl(counted_base_impl const &);
199     counted_base_impl & operator= (counted_base_impl const &);
200
201 public:
202
203     // pre: initial_use_count <= initial_weak_count, d(p) must not throw
204
205     counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
206         counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
207     {
208     }
209
210     virtual void dispose() // nothrow
211     {
212         del(ptr);
213     }
214 };
215
216 class weak_count;
217
218 class shared_count
219 {
220 private:
221
222     counted_base * pi_;
223
224     friend class weak_count;
225
226     template<class P, class D> shared_count(P, D, counted_base const *);
227
228 public:
229
230     shared_count(): pi_(new counted_base(1, 1))
231     {
232     }
233
234     explicit shared_count(counted_base * pi): pi_(pi) // never throws
235     {
236         pi_->add_ref();
237     }
238
239     template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
240     {
241 #ifndef BOOST_NO_EXCEPTIONS
242         try
243         {
244             pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
245         }
246         catch(...)
247         {
248             d(p); // delete p
249             throw;
250         }
251 #else
252         pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
253         BOOST_NOEH_ASSERT(pi_);
254 #endif
255     }
256
257     template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
258     {
259         pi_->add_ref();
260     }
261
262 #ifndef BOOST_NO_AUTO_PTR
263
264     // auto_ptr<Y> is special cased to provide the strong guarantee
265
266     template<typename Y>
267     explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
268     {
269         r.release();
270     }
271
272 #endif
273
274     ~shared_count() // nothrow
275     {
276         pi_->release();
277     }
278
279     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
280     {
281         pi_->add_ref();
282     }
283
284     explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
285
286     shared_count & operator= (shared_count const & r) // nothrow
287     {
288         counted_base * tmp = r.pi_;
289         tmp->add_ref();
290         pi_->release();
291         pi_ = tmp;
292
293         return *this;
294     }
295
296     void swap(shared_count & r) // nothrow
297     {
298         counted_base * tmp = r.pi_;
299         r.pi_ = pi_;
300         pi_ = tmp;
301     }
302
303     long use_count() const // nothrow
304     {
305         return pi_->use_count();
306     }
307
308     bool unique() const // nothrow
309     {
310         return pi_->use_count() == 1;
311     }
312
313     friend inline bool operator==(shared_count const & a, shared_count const & b)
314     {
315         return a.pi_ == b.pi_;
316     }
317
318     friend inline bool operator<(shared_count const & a, shared_count const & b)
319     {
320         return std::less<counted_base *>()(a.pi_, b.pi_);
321     }
322 };
323
324 class weak_count
325 {
326 private:
327
328     counted_base * pi_;
329
330     friend class shared_count;
331
332 public:
333
334     weak_count(): pi_(new counted_base(0, 1)) // can throw
335     {
336     }
337
338     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
339     {
340         pi_->weak_add_ref();
341     }
342
343     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
344     {
345         pi_->weak_add_ref();
346     }
347
348     ~weak_count() // nothrow
349     {
350         pi_->weak_release();
351     }
352
353     weak_count & operator= (shared_count const & r) // nothrow
354     {
355         counted_base * tmp = r.pi_;
356         tmp->weak_add_ref();
357         pi_->weak_release();
358         pi_ = tmp;
359
360         return *this;
361     }
362
363     weak_count & operator= (weak_count const & r) // nothrow
364     {
365         counted_base * tmp = r.pi_;
366         tmp->weak_add_ref();
367         pi_->weak_release();
368         pi_ = tmp;
369
370         return *this;
371     }
372
373     void swap(weak_count & r) // nothrow
374     {
375         counted_base * tmp = r.pi_;
376         r.pi_ = pi_;
377         pi_ = tmp;
378     }
379
380     long use_count() const // nothrow
381     {
382         return pi_->use_count();
383     }
384
385     friend inline bool operator==(weak_count const & a, weak_count const & b)
386     {
387         return a.pi_ == b.pi_;
388     }
389
390     friend inline bool operator<(weak_count const & a, weak_count const & b)
391     {
392         return std::less<counted_base *>()(a.pi_, b.pi_);
393     }
394 };
395
396 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
397 {
398     pi_->add_ref();
399 }
400
401 } // namespace detail
402
403 } // namespace boost
404
405 #ifdef __BORLANDC__
406 # pragma warn .8027     // Functions containing try are not expanded inline
407 # pragma warn .8026     // Functions with excep. spec. are not expanded inline
408 #endif
409
410 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED