10 #include "DM/config.hpp"
11 #include "DM/ObjectBaseRefCounting.hpp"
14 #include "NG_Exception.hpp"
18 DM_API
void *allocate_internal(
size_t);
19 DM_API
void deallocate_internal(
void *);
35 typedef const T * const_pointer;
36 typedef T & reference;
37 typedef const T & const_reference;
40 typedef std::size_t size_type;
41 typedef std::ptrdiff_t difference_type;
49 static pointer address(reference r) {
return &r; }
50 static const_pointer address(const_reference r) {
return &r; }
52 static pointer allocate(
const size_type n,
const pointer = 0)
53 {
return (pointer)allocate_internal(n *
sizeof(T)); }
55 static void deallocate(
const pointer p,
const size_type)
56 { deallocate_internal((
char *)p); }
57 static size_type max_size() {
return (std::numeric_limits<size_type>::max)(); }
59 bool operator==(
const Default_allocator &)
const {
return true; }
60 bool operator!=(
const Default_allocator &)
const {
return false; }
62 Default_allocator() { }
64 Default_allocator(
const Default_allocator<U> &) { }
66 static void construct(
const pointer p, const_reference t)
67 {
new ((
void *) p) T(t); }
68 static void destroy(
const pointer p)
74 template <
class T,
bool Thread_safe = true,
class C =
unsigned int,
class Alloc = Default_allocator<T> >
78 struct bool_tag {
typedef std::integral_constant<bool,Tb> type; };
81 template<
typename AnyT,
class CC =
unsigned int>
84 inline CC inc(T *t, CC
count)
const {
return count; }
85 inline CC dec(T *t, CC
count)
const {
return count; }
88 struct notify<std::true_type,CC> {
95 template<
class TT,
bool Thread_safe_,
class CC =
unsigned int>
97 typedef notify< typename std::is_base_of<ObjectBaseRefCounting, typename std::remove_pointer<T>::type >::type, CC> notify_type;
99 inline CC increaseCount() {
return notify_type().inc( t, ++
count ); }
100 inline CC decreaseCount() {
return notify_type().dec( t, --
count ); }
101 inline CC getCount()
const {
return static_cast<CC
const volatile &
>(
count ); }
104 std::atomic<CC>
count;
107 template<
class TT,
class CC>
108 struct RefCountedT<TT, false, CC > {
109 typedef notify< typename std::is_base_of<ObjectBaseRefCounting, typename std::remove_pointer<TT>::type >::type, CC> notify_type;
111 inline CC increaseCount() {
return notify_type().inc( t, ++
count); }
112 inline CC decreaseCount() {
return notify_type().dec( t, --
count); }
113 inline CC getCount()
const {
return count; }
120 typedef RefCountedT<T *, Thread_safe, C> RefCounted;
121 typedef typename Alloc::template rebind< RefCounted >::other Allocator;
122 typedef typename Allocator::pointer pointer;
124 static Allocator allocator;
130 void Delete(std::false_type& isScalar, T *&t) {
133 void Delete(std::true_type& isScalar, T *&t) {
134 throw NG_exception(
"scalar types are not suited for this Handle class, since the do not provide a Delete function");
139 typedef T element_type;
153 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
154 ptr_->increaseCount();
158 template<
class T2,
bool TS2,
class C2,
class A2>
159 Handle(
const Handle<T2, TS2, C2, A2> &other) : ptr_(0)
163 ptr_ = do_static_cast<T2, TS2, C2, A2,
164 typename std::is_base_of<T, T2>::type,
165 typename std::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
166 typename std::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
167 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
168 ptr_->increaseCount();
172 template<
class T2,
bool TS2,
class C2,
class A2>
173 Handle(
const Handle<T2, TS2, C2, A2> &other,
const use_static_cast &) : ptr_(0)
177 ptr_ = do_static_cast<T2, TS2, C2, A2,
178 typename std::true_type,
179 typename std::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
180 typename std::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
181 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
182 ptr_->increaseCount();
186 template<
class T2,
bool TS2,
class C2,
class A2>
187 Handle(
const Handle<T2, TS2, C2, A2> &other,
const use_dynamic_cast &) : ptr_(0)
191 ptr_ = do_dynamic_cast<T2, TS2, C2, A2,
192 typename std::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
193 typename std::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
196 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
197 ptr_->increaseCount();
202 Handle(T* p) : ptr_(0)
206 ptr_ = (allocator.allocate(1));
218 if (ptr_->decreaseCount() == 0 )
221 typename std::is_scalar<T>::type type;
222 Delete( type, ptr_->t );
223 allocator.destroy( ptr_);
224 allocator.deallocate( ptr_, 1);
229 Handle& operator=(
const Handle& h)
236 template<
class T2,
bool TS2,
class C2,
class A2>
237 Handle& operator=(
const Handle<T2, TS2, C2, A2> &other)
253 {
return reinterpret_cast<size_type
>(&*ptr_); }
263 operator const T &()
const {
273 return (ptr_) ? ptr_->t : 0;
276 const T & operator*()
const {
return *(ptr_->t); }
277 T & operator*() {
return *(ptr_->t); }
278 const T * operator->()
const {
return (ptr_) ? ptr_->t : 0; }
279 T * operator->() {
return (ptr_) ? ptr_->t : 0; }
281 bool is_shared()
const
283 return (ptr_ && ptr_->count > 1);
288 return (ptr_ ? ptr_->getCount() : 0);
295 if (ptr_->decreaseCount() != 0)
296 throw NG_exception(
"Shared objects (reference counter > 1) cannot be released");
299 allocator.destroy( ptr_);
300 allocator.deallocate( ptr_, 1);
309 std::swap(ptr_, h.ptr_);
319 return (ptr_ ? Handle( ptr_->t->clone() ) : Handle() );
322 bool operator==(
const Handle& h)
const
324 return (ptr_ == h.ptr_);
327 bool operator!=(
const Handle& h)
const
329 return (ptr_ != h.ptr_);
332 bool operator>(
const Handle& h)
const
334 return (ptr_ > h.ptr_);
337 bool operator<(
const Handle& h)
const
339 return (ptr_ < h.ptr_);
342 typedef const T * (
self::*unspecified_bool_type)()
const;
344 operator unspecified_bool_type()
const
353 template<
typename T2,
bool TS2,
class C2,
class A2,
typename BaseFlag,
typename SameThreadFlag,
typename SameAllocFlag>
355 RefCounted * operator()(
const typename Handle<T2, TS2, C2, A2>::RefCounted *ptr) {
356 static_assert(
sizeof(ptr)==0);
366 template<
typename T2,
bool TS2,
class A2>
367 struct do_static_cast<T2, TS2, C, A2, std::false_type, std::true_type, std::true_type> {
368 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
369 static_assert(
sizeof(ptr)==0);
376 template<
typename T2,
bool TS2,
class A2>
377 struct do_static_cast<T2, TS2, C, A2, std::true_type, std::true_type, std::true_type> {
378 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
379 return (RefCounted *)((
void *)(ptr));
386 template<
typename T2,
bool TS2,
class C2,
class A2,
typename SameThreadFlag,
typename SameAllocFlag>
388 RefCounted * operator()(
const typename Handle<T2, TS2, C2, A2>::RefCounted *ptr) {
389 static_assert(
sizeof(ptr)==0);
399 template<
typename T2,
bool TS2,
class A2>
401 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
402 T *p =
dynamic_cast<T*
>(ptr->t);
404 return (RefCounted *)((
void *)(ptr));
411 template<
class T2,
bool TT2,
class C2,
class A2>
416 template <
class T,
bool TT,
class C,
class Allocator>
417 typename Handle<T, TT, C, Allocator>::Allocator
420 template <
class T,
bool TT,
class C,
class Allocator>
435 typedef T element_type;
450 StaticHandle(
const StaticHandle<T2> &other) : ptr_(0)
454 ptr_ = do_static_cast<T2, typename std::is_base_of<T, T2>::type >()(other.ptr_);
459 StaticHandle(
const StaticHandle<T2> &other,
const use_static_cast &) : ptr_(0)
463 ptr_ = do_static_cast<T2, std::true_type >()(other.ptr_);
468 StaticHandle(
const StaticHandle<T2> &other,
const use_dynamic_cast &) : ptr_(0)
472 ptr_ = do_dynamic_cast<T2>()(other.ptr_);
476 StaticHandle(T* p) : ptr_(p)
484 StaticHandle& operator=(
const StaticHandle& h)
491 StaticHandle& operator=(
const StaticHandle<T2> &other)
493 StaticHandle tmp = other;
507 {
return reinterpret_cast<size_type
>(ptr_); }
509 operator const T &()
const {
518 T &operator*()
const {
return *(ptr_); }
519 T *operator->()
const {
return (ptr_); }
531 void swap(StaticHandle& h)
533 std::swap(ptr_, h.ptr_);
540 StaticHandle clone()
const
542 return StaticHandle(ptr_);
545 bool operator==(
const StaticHandle& h)
const
547 return (ptr_ == h.ptr_);
550 bool operator!=(
const StaticHandle& h)
const
552 return (ptr_ != h.ptr_);
555 bool operator>(
const StaticHandle& h)
const
557 return (ptr_ > h.ptr_);
560 bool operator<(
const StaticHandle& h)
const
562 return (ptr_ < h.ptr_);
565 operator bool()
const
567 return ptr_ != (T *)0;
572 template<
typename T2,
typename TagT>
574 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
575 static_assert(
sizeof(ptr)==0);
581 template<
typename T2>
583 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
584 return (pointer)(ptr);
588 template<
typename T2>
590 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
591 return dynamic_cast<pointer
>(ptr);