1 #ifndef DM_HANDLE_HPP_INCLUDED
2 #define DM_HANDLE_HPP_INCLUDED
10 # include <boost/detail/interlocked.hpp>
14 #ifdef BOOST_INTERLOCKED_INCREMENT // Windows
15 #define IPF_ATOMIC_UNSIGNED unsigned int
16 #define IPF_ATOMIC_INCREMENT(a) BOOST_INTERLOCKED_INCREMENT((long volatile *)&a)
17 #define IPF_ATOMIC_DECREMENT(a) BOOST_INTERLOCKED_DECREMENT((long volatile *)&a)
19 #elif defined(__GNUG__) // Linux
22 #define IPF_ATOMIC_UNSIGNED std::atomic<unsigned int>
23 #define IPF_ATOMIC_INCREMENT(a) static_cast<unsigned volatile>(++(a))
24 #define IPF_ATOMIC_DECREMENT(a) static_cast<unsigned volatile>(--(a))
27 # error "Unable to find atomic"
30 #include <boost/type_traits/is_base_of.hpp>
31 #include <boost/type_traits/remove_pointer.hpp>
32 #include <boost/type_traits/is_scalar.hpp>
33 #include <boost/static_assert.hpp>
38 #include "DM/config.hpp"
39 #include "DM/ObjectBaseRefCounting.hpp"
42 #include "NG_Exception.hpp"
46 DM_API
void *allocate_internal(
size_t);
47 DM_API
void deallocate_internal(
void *);
63 typedef const T * const_pointer;
64 typedef T & reference;
65 typedef const T & const_reference;
68 typedef std::size_t size_type;
69 typedef std::ptrdiff_t difference_type;
77 static pointer address(reference r) {
return &r; }
78 static const_pointer address(const_reference r) {
return &r; }
80 static pointer allocate(
const size_type n,
const pointer = 0)
81 {
return (pointer)allocate_internal(n *
sizeof(T)); }
83 static void deallocate(
const pointer p,
const size_type)
84 { deallocate_internal((
char *)p); }
85 static size_type max_size() {
return (std::numeric_limits<size_type>::max)(); }
87 bool operator==(
const Default_allocator &)
const {
return true; }
88 bool operator!=(
const Default_allocator &)
const {
return false; }
90 Default_allocator() { }
92 Default_allocator(
const Default_allocator<U> &) { }
94 static void construct(
const pointer p, const_reference t)
95 {
new ((
void *) p) T(t); }
96 static void destroy(
const pointer p)
102 template <
class T,
bool Thread_safe = true,
class C =
unsigned int,
class Alloc = Default_allocator<T> >
106 struct bool_tag {
typedef boost::integral_constant<bool,Tb> type; };
109 template<
typename AnyT,
class CC =
unsigned int>
112 inline CC inc(T *t, CC count)
const {
return count; }
113 inline CC dec(T *t, CC count)
const {
return count; }
116 struct notify<boost::true_type,CC> {
118 inline CC inc(T *t, CC count)
const {
static_cast<ObjectBaseRefCounting *
>(t)->refAdded(count);
return count; }
119 inline CC dec(T *t, CC count)
const {
static_cast<ObjectBaseRefCounting *
>(t)->refRemoved(count);
return count; }
123 template<
class TT,
bool Thread_safe_,
class CC =
unsigned int>
125 typedef notify< typename boost::is_base_of<ObjectBaseRefCounting, typename boost::remove_pointer<T>::type >::type, CC> notify_type;
127 inline CC increaseCount() {
return notify_type().inc( t, IPF_ATOMIC_INCREMENT(count) ); }
128 inline CC decreaseCount() {
return notify_type().dec( t, IPF_ATOMIC_DECREMENT(count) ); }
129 inline CC getCount()
const {
return static_cast<CC
const volatile &
>( count ); }
132 #if defined(__GNUG__) // Linux
133 std::atomic<CC> count;
139 template<
class TT,
class CC>
140 struct RefCountedT<TT, false, CC > {
141 typedef notify< typename boost::is_base_of<ObjectBaseRefCounting, typename boost::remove_pointer<TT>::type >::type, CC> notify_type;
143 inline CC increaseCount() {
return notify_type().inc( t, ++count); }
144 inline CC decreaseCount() {
return notify_type().dec( t, --count); }
145 inline CC getCount()
const {
return count; }
152 typedef RefCountedT<T *, Thread_safe, C> RefCounted;
153 typedef typename Alloc::template rebind< RefCounted >::other Allocator;
154 typedef typename Allocator::pointer pointer;
156 static Allocator allocator;
162 void Delete(boost::false_type& isScalar, T *&t) {
165 void Delete(boost::true_type& isScalar, T *&t) {
166 throw NG_exception(
"scalar types are not suited for this Handle class, since the do not provide a Delete function");
171 typedef T element_type;
185 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
186 ptr_->increaseCount();
190 template<
class T2,
bool TS2,
class C2,
class A2>
191 Handle(
const Handle<T2, TS2, C2, A2> &other) : ptr_(0)
195 ptr_ = do_static_cast<T2, TS2, C2, A2,
196 typename boost::is_base_of<T, T2>::type,
197 typename boost::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
198 typename boost::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
199 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
200 ptr_->increaseCount();
204 template<
class T2,
bool TS2,
class C2,
class A2>
205 Handle(
const Handle<T2, TS2, C2, A2> &other,
const use_static_cast &) : ptr_(0)
209 ptr_ = do_static_cast<T2, TS2, C2, A2,
210 typename boost::true_type,
211 typename boost::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
212 typename boost::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
213 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
214 ptr_->increaseCount();
218 template<
class T2,
bool TS2,
class C2,
class A2>
219 Handle(
const Handle<T2, TS2, C2, A2> &other,
const use_dynamic_cast &) : ptr_(0)
223 ptr_ = do_dynamic_cast<T2, TS2, C2, A2,
224 typename boost::is_same<bool_tag<Thread_safe>, bool_tag<TS2>>::type,
225 typename boost::is_same<Allocator, typename A2::template rebind< RefCounted >::other>::type >()(other.ptr_);
228 assert( (ptr_->count) < (std::numeric_limits<C>::max)() );
229 ptr_->increaseCount();
234 Handle(T* p) : ptr_(0)
238 ptr_ = (allocator.allocate(1));
250 if (ptr_->decreaseCount() == 0 )
253 typename boost::is_scalar<T>::type type;
254 Delete( type, ptr_->t );
255 allocator.destroy( ptr_);
256 allocator.deallocate( ptr_, 1);
261 Handle& operator=(
const Handle& h)
268 template<
class T2,
bool TS2,
class C2,
class A2>
269 Handle& operator=(
const Handle<T2, TS2, C2, A2> &other)
285 {
return reinterpret_cast<size_type
>(&*ptr_); }
295 operator const T &()
const {
305 return (ptr_) ? ptr_->t : 0;
308 const T & operator*()
const {
return *(ptr_->t); }
309 T & operator*() {
return *(ptr_->t); }
310 const T * operator->()
const {
return (ptr_) ? ptr_->t : 0; }
311 T * operator->() {
return (ptr_) ? ptr_->t : 0; }
313 bool is_shared()
const
315 return (ptr_ && ptr_->count > 1);
320 return (ptr_ ? ptr_->getCount() : 0);
327 if (ptr_->decreaseCount() != 0)
328 throw NG_exception(
"Shared objects (reference counter > 1) cannot be released");
331 allocator.destroy( ptr_);
332 allocator.deallocate( ptr_, 1);
341 std::swap(ptr_, h.ptr_);
351 return (ptr_ ? Handle( ptr_->t->clone() ) : Handle() );
356 return (ptr_ == h.ptr_);
361 return (ptr_ != h.ptr_);
366 return (ptr_ > h.ptr_);
371 return (ptr_ < h.ptr_);
374 typedef const T * (
self::*unspecified_bool_type)()
const;
376 operator unspecified_bool_type()
const
385 template<
typename T2,
bool TS2,
class C2,
class A2,
typename BaseFlag,
typename SameThreadFlag,
typename SameAllocFlag>
387 RefCounted * operator()(
const typename Handle<T2, TS2, C2, A2>::RefCounted *ptr) {
388 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
398 template<
typename T2,
bool TS2,
class A2>
399 struct do_static_cast<T2, TS2, C, A2, boost::false_type, boost::true_type, boost::true_type> {
400 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
401 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
408 template<
typename T2,
bool TS2,
class A2>
409 struct do_static_cast<T2, TS2, C, A2, boost::true_type, boost::true_type, boost::true_type> {
410 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
411 return (RefCounted *)((
void *)(ptr));
418 template<
typename T2,
bool TS2,
class C2,
class A2,
typename SameThreadFlag,
typename SameAllocFlag>
420 RefCounted * operator()(
const typename Handle<T2, TS2, C2, A2>::RefCounted *ptr) {
421 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
431 template<
typename T2,
bool TS2,
class A2>
433 RefCounted * operator()(
const typename Handle<T2, TS2, C, A2>::RefCounted *ptr) {
434 T *p =
dynamic_cast<T*
>(ptr->t);
436 return (RefCounted *)((
void *)(ptr));
443 template<
class T2,
bool TT2,
class C2,
class A2>
448 template <
class T,
bool TT,
class C,
class Allocator>
449 typename Handle<T, TT, C, Allocator>::Allocator
452 template <
class T,
bool TT,
class C,
class Allocator>
467 typedef T element_type;
482 StaticHandle(
const StaticHandle<T2> &other) : ptr_(0)
486 ptr_ = do_static_cast<T2,
typename boost::is_base_of<T, T2>::type >()(other.ptr_);
491 StaticHandle(
const StaticHandle<T2> &other,
const use_static_cast &) : ptr_(0)
495 ptr_ = do_static_cast<T2, boost::true_type >()(other.ptr_);
500 StaticHandle(
const StaticHandle<T2> &other,
const use_dynamic_cast &) : ptr_(0)
504 ptr_ = do_dynamic_cast<T2>()(other.ptr_);
508 StaticHandle(T* p) : ptr_(p)
516 StaticHandle& operator=(
const StaticHandle& h)
523 StaticHandle& operator=(
const StaticHandle<T2> &other)
525 StaticHandle tmp = other;
539 {
return reinterpret_cast<size_type
>(ptr_); }
541 operator const T &()
const {
550 T &operator*()
const {
return *(ptr_); }
551 T *operator->()
const {
return (ptr_); }
563 void swap(StaticHandle& h)
565 std::swap(ptr_, h.ptr_);
572 StaticHandle clone()
const
574 return StaticHandle(ptr_);
579 return (ptr_ == h.ptr_);
584 return (ptr_ != h.ptr_);
587 bool operator>(
const StaticHandle& h)
const
589 return (ptr_ > h.ptr_);
592 bool operator<(
const StaticHandle& h)
const
594 return (ptr_ < h.ptr_);
597 operator bool()
const
599 return ptr_ != (T *)0;
604 template<
typename T2,
typename TagT>
606 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
607 BOOST_STATIC_ASSERT(
sizeof(ptr)==0);
613 template<
typename T2>
615 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
616 return (pointer)(ptr);
620 template<
typename T2>
622 pointer operator()(
const typename StaticHandle<T2>::pointer *ptr) {
623 return dynamic_cast<pointer
>(ptr);
637 #endif //DM_HANDLE_HPP_INCLUDED