5 # include <boost/detail/interlocked.hpp>
9 #ifdef BOOST_INTERLOCKED_INCREMENT // Windows
10 #define IPF_ATOMIC_UNSIGNED unsigned int
11 #define IPF_ATOMIC_INCREMENT(a) BOOST_INTERLOCKED_INCREMENT((long volatile *)&a)
12 #define IPF_ATOMIC_DECREMENT(a) BOOST_INTERLOCKED_DECREMENT((long volatile *)&a)
14 #elif defined(__GNUG__) // Linux
17 #define IPF_ATOMIC_UNSIGNED std::atomic<unsigned int>
18 #define IPF_ATOMIC_INCREMENT(a) static_cast<unsigned volatile>(++(a))
19 #define IPF_ATOMIC_DECREMENT(a) static_cast<unsigned volatile>(--(a))
22 # error "Unable to find atomic"
25 #include <boost/type_traits/is_base_of.hpp>
26 #include <boost/type_traits/remove_pointer.hpp>
27 #include <boost/type_traits/is_scalar.hpp>
28 #include <boost/static_assert.hpp>
33 #include "DM/config.hpp"
34 #include "DM/ObjectBaseRefCounting.hpp"
37 #include "NG_Exception.hpp"
41 DM_API
void *allocate_internal(
size_t);
42 DM_API
void deallocate_internal(
void *);
58 typedef const T * const_pointer;
59 typedef T & reference;
60 typedef const T & const_reference;
63 typedef std::size_t size_type;
64 typedef std::ptrdiff_t difference_type;
72 static pointer address(reference r) {
return &r; }
73 static const_pointer address(const_reference r) {
return &r; }
75 static pointer allocate(
const size_type n,
const pointer = 0)
76 {
return (pointer)allocate_internal(n *
sizeof(T)); }
78 static void deallocate(
const pointer p,
const size_type)
79 { deallocate_internal((
char *)p); }
80 static size_type max_size() {
return (std::numeric_limits<size_type>::max)(); }
82 bool operator==(
const Default_allocator &)
const {
return true; }
83 bool operator!=(
const Default_allocator &)
const {
return false; }
85 Default_allocator() { }
87 Default_allocator(
const Default_allocator<U> &) { }
89 static void construct(
const pointer p, const_reference t)
90 {
new ((
void *) p) T(t); }
91 static void destroy(
const pointer p)
97 template <
class T,
bool Thread_safe = true,
class C =
unsigned int,
class Alloc = Default_allocator<T> >
101 struct bool_tag {
typedef boost::integral_constant<bool,Tb> type; };
104 template<
typename AnyT,
class CC =
unsigned int>
107 inline CC inc(T *t, CC
count)
const {
return count; }
108 inline CC dec(T *t, CC
count)
const {
return count; }
111 struct notify<boost::true_type,CC> {
118 template<
class TT,
bool Thread_safe_,
class CC =
unsigned int>
120 typedef notify< typename boost::is_base_of<ObjectBaseRefCounting, typename boost::remove_pointer<T>::type >::type, CC> notify_type;
122 inline CC increaseCount() {
return notify_type().inc( t, IPF_ATOMIC_INCREMENT(
count) ); }
123 inline CC decreaseCount() {
return notify_type().dec( t, IPF_ATOMIC_DECREMENT(
count) ); }
124 inline CC getCount()
const {
return static_cast<CC
const volatile &
>(
count ); }
127 #if defined(__GNUG__) // Linux
128 std::atomic<CC>
count;
134 template<
class TT,
class CC>
135 struct RefCountedT<TT, false, CC > {
136 typedef notify< typename boost::is_base_of<ObjectBaseRefCounting, typename boost::remove_pointer<TT>::type >::type, CC> notify_type;
138 inline CC increaseCount() {
return notify_type().inc( t, ++
count); }
139 inline CC decreaseCount() {
return notify_type().dec( t, --
count); }
140 inline CC getCount()
const {
return count; }
147 typedef RefCountedT<T *, Thread_safe, C> RefCounted;
148 typedef typename Alloc::template rebind< RefCounted >::other Allocator;
149 typedef typename Allocator::pointer pointer;
151 static Allocator allocator;
157 void Delete(boost::false_type& isScalar, T *&t) {
160 void Delete(boost::true_type& isScalar, T *&t) {
161 throw NG_exception(
"scalar types are not suited for this Handle class, since the do not provide a Delete function");
166 typedef T element_type;
180 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
181 ptr_->increaseCount();
185 template<
class T2,
bool TS2,
class C2,
class A2>
186 Handle(
const Handle<T2, TS2, C2, A2> &other) : ptr_(0)
190 ptr_ = do_static_cast<T2, TS2, C2, A2,
191 typename boost::is_base_of<T, T2>::type,
192 typename boost::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
193 typename boost::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
194 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
195 ptr_->increaseCount();
199 template<
class T2,
bool TS2,
class C2,
class A2>
200 Handle(
const Handle<T2, TS2, C2, A2> &other,
const use_static_cast &) : ptr_(0)
204 ptr_ = do_static_cast<T2, TS2, C2, A2,
205 typename boost::true_type,
206 typename boost::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
207 typename boost::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
208 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
209 ptr_->increaseCount();
213 template<
class T2,
bool TS2,
class C2,
class A2>
214 Handle(
const Handle<T2, TS2, C2, A2> &other,
const use_dynamic_cast &) : ptr_(0)
218 ptr_ = do_dynamic_cast<T2, TS2, C2, A2,
219 typename boost::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
220 typename boost::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
223 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
224 ptr_->increaseCount();
229 Handle(T* p) : ptr_(0)
233 ptr_ = (allocator.allocate(1));
245 if (ptr_->decreaseCount() == 0 )
248 typename boost::is_scalar<T>::type type;
249 Delete( type, ptr_->t );
250 allocator.destroy( ptr_);
251 allocator.deallocate( ptr_, 1);
256 Handle& operator=(
const Handle& h)
263 template<
class T2,
bool TS2,
class C2,
class A2>
264 Handle& operator=(
const Handle<T2, TS2, C2, A2> &other)
280 {
return reinterpret_cast<size_type
>(&*ptr_); }
290 operator const T &()
const {
300 return (ptr_) ? ptr_->t : 0;
303 const T & operator*()
const {
return *(ptr_->t); }
304 T & operator*() {
return *(ptr_->t); }
305 const T * operator->()
const {
return (ptr_) ? ptr_->t : 0; }
306 T * operator->() {
return (ptr_) ? ptr_->t : 0; }
308 bool is_shared()
const
310 return (ptr_ && ptr_->count > 1);
315 return (ptr_ ? ptr_->getCount() : 0);
322 if (ptr_->decreaseCount() != 0)
323 throw NG_exception(
"Shared objects (reference counter > 1) cannot be released");
326 allocator.destroy( ptr_);
327 allocator.deallocate( ptr_, 1);
336 std::swap(ptr_, h.ptr_);
346 return (ptr_ ? Handle( ptr_->t->clone() ) : Handle() );
349 bool operator==(
const Handle& h)
const
351 return (ptr_ == h.ptr_);
354 bool operator!=(
const Handle& h)
const
356 return (ptr_ != h.ptr_);
359 bool operator>(
const Handle& h)
const
361 return (ptr_ > h.ptr_);
364 bool operator<(
const Handle& h)
const
366 return (ptr_ < h.ptr_);
369 typedef const T * (
self::*unspecified_bool_type)()
const;
371 operator unspecified_bool_type()
const
380 template<
typename T2,
bool TS2,
class C2,
class A2,
typename BaseFlag,
typename SameThreadFlag,
typename SameAllocFlag>
382 RefCounted * operator()(
const typename Handle<T2, TS2, C2, A2>::RefCounted *ptr) {
383 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
393 template<
typename T2,
bool TS2,
class A2>
394 struct do_static_cast<T2, TS2, C, A2, boost::false_type, boost::true_type, boost::true_type> {
395 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
396 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
403 template<
typename T2,
bool TS2,
class A2>
404 struct do_static_cast<T2, TS2, C, A2, boost::true_type, boost::true_type, boost::true_type> {
405 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
406 return (RefCounted *)((
void *)(ptr));
413 template<
typename T2,
bool TS2,
class C2,
class A2,
typename SameThreadFlag,
typename SameAllocFlag>
415 RefCounted * operator()(
const typename Handle<T2, TS2, C2, A2>::RefCounted *ptr) {
416 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
426 template<
typename T2,
bool TS2,
class A2>
428 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
429 T *p =
dynamic_cast<T*
>(ptr->t);
431 return (RefCounted *)((
void *)(ptr));
438 template<
class T2,
bool TT2,
class C2,
class A2>
443 template <
class T,
bool TT,
class C,
class Allocator>
444 typename Handle<T, TT, C, Allocator>::Allocator
447 template <
class T,
bool TT,
class C,
class Allocator>
462 typedef T element_type;
477 StaticHandle(
const StaticHandle<T2> &other) : ptr_(0)
481 ptr_ = do_static_cast<T2, typename boost::is_base_of<T, T2>::type >()(other.ptr_);
486 StaticHandle(
const StaticHandle<T2> &other,
const use_static_cast &) : ptr_(0)
490 ptr_ = do_static_cast<T2, boost::true_type >()(other.ptr_);
495 StaticHandle(
const StaticHandle<T2> &other,
const use_dynamic_cast &) : ptr_(0)
499 ptr_ = do_dynamic_cast<T2>()(other.ptr_);
503 StaticHandle(T* p) : ptr_(p)
511 StaticHandle& operator=(
const StaticHandle& h)
518 StaticHandle& operator=(
const StaticHandle<T2> &other)
520 StaticHandle tmp = other;
534 {
return reinterpret_cast<size_type
>(ptr_); }
536 operator const T &()
const {
545 T &operator*()
const {
return *(ptr_); }
546 T *operator->()
const {
return (ptr_); }
558 void swap(StaticHandle& h)
560 std::swap(ptr_, h.ptr_);
567 StaticHandle clone()
const
569 return StaticHandle(ptr_);
572 bool operator==(
const StaticHandle& h)
const
574 return (ptr_ == h.ptr_);
577 bool operator!=(
const StaticHandle& h)
const
579 return (ptr_ != h.ptr_);
582 bool operator>(
const StaticHandle& h)
const
584 return (ptr_ > h.ptr_);
587 bool operator<(
const StaticHandle& h)
const
589 return (ptr_ < h.ptr_);
592 operator bool()
const
594 return ptr_ != (T *)0;
599 template<
typename T2,
typename TagT>
601 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
602 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
608 template<
typename T2>
610 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
611 return (pointer)(ptr);
615 template<
typename T2>
617 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
618 return dynamic_cast<pointer
>(ptr);