]> git.lyx.org Git - features.git/blob - boost/boost/detail/shared_count.hpp
dont throw, assert or ponder on instead
[features.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 #if 0
30 #include <exception>        // for std::exception
31 #endif
32
33 namespace boost
34 {
35
36 #if 0
37 class use_count_is_zero: public std::exception
38 {
39 public:
40
41     virtual char const * what() const throw()
42     {
43         return "use_count_is_zero";
44     }
45 };
46 #endif
47
48 class counted_base
49 {
50 private:
51
52     typedef detail::lightweight_mutex mutex_type;
53
54 public:
55
56     counted_base():
57         use_count_(0), weak_count_(0), self_deleter_(&self_delete)
58     {
59     }
60
61     // pre: initial_use_count <= initial_weak_count
62
63     explicit counted_base(long initial_use_count, long initial_weak_count):
64         use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
65     {
66     }
67
68     virtual ~counted_base() // nothrow
69     {
70     }
71
72     // dispose() is called when use_count_ drops to zero, to release
73     // the resources managed by *this.
74     //
75     // counted_base doesn't manage any resources except itself, and
76     // the default implementation is a no-op.
77     //
78     // dispose() is not pure virtual since weak_ptr instantiates a
79     // counted_base in its default constructor.
80
81     virtual void dispose() // nothrow
82     {
83     }
84
85     void add_ref()
86     {
87 #ifdef BOOST_HAS_THREADS
88         mutex_type::scoped_lock lock(mtx_);
89 #endif
90 #if 0
91         if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
92 #else
93         if(use_count_ == 0 && weak_count_ != 0) assert(false);
94 #endif
95         ++use_count_;
96         ++weak_count_;
97     }
98
99     void release() // nothrow
100     {
101         long new_use_count;
102         long new_weak_count;
103
104         {
105 #ifdef BOOST_HAS_THREADS
106             mutex_type::scoped_lock lock(mtx_);
107 #endif
108             new_use_count = --use_count_;
109             new_weak_count = --weak_count_;
110         }
111
112         if(new_use_count == 0)
113         {
114             dispose();
115         }
116
117         if(new_weak_count == 0)
118         {
119             // not a direct 'delete this', because the inlined
120             // release() may use a different heap manager
121             self_deleter_(this);
122         }
123     }
124
125     void weak_add_ref() // nothrow
126     {
127 #ifdef BOOST_HAS_THREADS
128         mutex_type::scoped_lock lock(mtx_);
129 #endif
130         ++weak_count_;
131     }
132
133     void weak_release() // nothrow
134     {
135         long new_weak_count;
136
137         {
138 #ifdef BOOST_HAS_THREADS
139             mutex_type::scoped_lock lock(mtx_);
140 #endif
141             new_weak_count = --weak_count_;
142         }
143
144         if(new_weak_count == 0)
145         {
146             self_deleter_(this);
147         }
148     }
149
150     long use_count() const // nothrow
151     {
152 #ifdef BOOST_HAS_THREADS
153         mutex_type::scoped_lock lock(mtx_);
154 #endif
155         return use_count_;
156     }
157
158 private:
159
160     counted_base(counted_base const &);
161     counted_base & operator= (counted_base const &);
162
163     static void self_delete(counted_base * p)
164     {
165         delete p;
166     }
167
168     // inv: use_count_ <= weak_count_
169
170     long use_count_;
171     long weak_count_;
172 #ifdef BOOST_HAS_THREADS
173     mutable mutex_type mtx_;
174 #endif
175     void (*self_deleter_) (counted_base *);
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 #if 0
242         try
243         {
244 #endif
245             pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
246 #if 0
247         }
248         catch(...)
249         {
250             d(p); // delete p
251             throw;
252         }
253 #endif
254     }
255
256     template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
257     {
258         pi_->add_ref();
259     }
260
261 #ifndef BOOST_NO_AUTO_PTR
262
263     // auto_ptr<Y> is special cased to provide the strong guarantee
264
265     template<typename Y>
266     explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
267     {
268         r.release();
269     }
270
271 #endif
272
273     ~shared_count() // nothrow
274     {
275         pi_->release();
276     }
277
278     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
279     {
280         pi_->add_ref();
281     }
282
283     explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
284
285     shared_count & operator= (shared_count const & r) // nothrow
286     {
287         counted_base * tmp = r.pi_;
288         tmp->add_ref();
289         pi_->release();
290         pi_ = tmp;
291
292         return *this;
293     }
294
295     void swap(shared_count & r) // nothrow
296     {
297         counted_base * tmp = r.pi_;
298         r.pi_ = pi_;
299         pi_ = tmp;
300     }
301
302     long use_count() const // nothrow
303     {
304         return pi_->use_count();
305     }
306
307     bool unique() const // nothrow
308     {
309         return pi_->use_count() == 1;
310     }
311
312     friend inline bool operator==(shared_count const & a, shared_count const & b)
313     {
314         return a.pi_ == b.pi_;
315     }
316
317     friend inline bool operator<(shared_count const & a, shared_count const & b)
318     {
319         return std::less<counted_base *>()(a.pi_, b.pi_);
320     }
321 };
322
323 class weak_count
324 {
325 private:
326
327     counted_base * pi_;
328
329     friend class shared_count;
330
331 public:
332
333     weak_count(): pi_(new counted_base(0, 1)) // can throw
334     {
335     }
336
337     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
338     {
339         pi_->weak_add_ref();
340     }
341
342     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
343     {
344         pi_->weak_add_ref();
345     }
346
347     ~weak_count() // nothrow
348     {
349         pi_->weak_release();
350     }
351
352     weak_count & operator= (shared_count const & r) // nothrow
353     {
354         counted_base * tmp = r.pi_;
355         tmp->weak_add_ref();
356         pi_->weak_release();
357         pi_ = tmp;
358
359         return *this;
360     }
361
362     weak_count & operator= (weak_count const & r) // nothrow
363     {
364         counted_base * tmp = r.pi_;
365         tmp->weak_add_ref();
366         pi_->weak_release();
367         pi_ = tmp;
368
369         return *this;
370     }
371
372     void swap(weak_count & r) // nothrow
373     {
374         counted_base * tmp = r.pi_;
375         r.pi_ = pi_;
376         pi_ = tmp;
377     }
378
379     long use_count() const // nothrow
380     {
381         return pi_->use_count();
382     }
383
384     friend inline bool operator==(weak_count const & a, weak_count const & b)
385     {
386         return a.pi_ == b.pi_;
387     }
388
389     friend inline bool operator<(weak_count const & a, weak_count const & b)
390     {
391         return std::less<counted_base *>()(a.pi_, b.pi_);
392     }
393 };
394
395 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
396 {
397     pi_->add_ref();
398 }
399
400 } // namespace detail
401
402 } // namespace boost
403
404 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED