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