///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Matei David 2014 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// #ifndef BOUNDED_POINTER_HPP #define BOUNDED_POINTER_HPP #include #include #include #include #include #include #include #include #include #define CONST_CONVERSIONS(_type, _t) \ operator const _type< typename boost::add_const< _t >::type >& () const \ { return *reinterpret_cast< const _type< typename boost::add_const< _t >::type >* >(this); } \ operator _type< typename boost::add_const< _t >::type >& () \ { return *reinterpret_cast< _type< typename boost::add_const< _t >::type >* >(this); } \ \ const _type< typename boost::remove_const< _t >::type >& unconst() const \ { return *reinterpret_cast< const _type< typename boost::remove_const< _t >::type >* >(this); } \ _type< typename boost::remove_const< _t >::type >& unconst() \ { return *reinterpret_cast< _type< typename boost::remove_const< _t >::type >* >(this); } template < typename T > class Bounded_Pointer; template < typename T > class Bounded_Reference; template < typename T > class Bounded_Allocator; template < typename T > class Bounded_Pointer { public: typedef typename boost::remove_const< T >::type mut_val_t; typedef const mut_val_t const_val_t; template struct rebind { typedef typename boost::mpl::if_< boost::is_same< typename boost::remove_const< U >::type, typename boost::remove_const< T >::type >, Bounded_Pointer< U >, U* >::type type; }; Bounded_Pointer() : _offset(255) {} Bounded_Pointer(const Bounded_Pointer& other) : _offset(other._offset) {} Bounded_Pointer& operator = (const Bounded_Pointer& other) { _offset = other._offset; return *this; } CONST_CONVERSIONS(Bounded_Pointer, T) static mut_val_t* base() { assert(Bounded_Allocator< mut_val_t >::inited()); return &Bounded_Allocator< mut_val_t >::_base[0]; } operator bool() const { return _offset != 255; } T* raw() const { return base() + _offset; } Bounded_Reference< T > operator * () const { return Bounded_Reference< T >(*this); } T* operator -> () const { return raw(); } Bounded_Pointer& operator ++ () { ++_offset; return *this; } Bounded_Pointer operator ++ (int) { Bounded_Pointer res(*this); ++(*this); return res; } template < typename U > // typename boost::enable_if< boost::is_same< typename boost::remove_const< U >::type, // typename boost::remove_const< T >::type >, int >::type = 42 > bool operator == (const Bounded_Pointer< U >& rhs) const { return _offset == rhs._offset; } template < typename U > // typename boost::enable_if< boost::is_same< typename boost::remove_const< U >::type, // typename boost::remove_const< T >::type >, int >::type = 42 > bool operator < (const Bounded_Pointer< U >& rhs) const { return _offset < rhs._offset; } friend std::ostream& operator << (std::ostream& os, const Bounded_Pointer< T >& ptr) { os << static_cast< int >(ptr._offset); return os; } private: template friend class Bounded_Pointer; friend class Bounded_Reference< T >; friend class Bounded_Allocator< T >; uint8_t _offset; }; // class Bounded_Pointer template < typename T > class Bounded_Reference { public: typedef typename boost::remove_const< T >::type mut_val_t; typedef const mut_val_t const_val_t; Bounded_Reference() : _offset(255) {} Bounded_Reference(const Bounded_Reference& other) : _offset(other._offset) {} CONST_CONVERSIONS(Bounded_Reference, T) T& raw() const { assert(_offset != 255); return *(Bounded_Pointer< T >::base() + _offset); } operator T& () const { assert(_offset != 255); return raw(); } Bounded_Pointer< T > operator & () const { assert(_offset != 255); Bounded_Pointer< T > res; res._offset = _offset; return res; } Bounded_Reference& operator = (const T& rhs) { assert(_offset != 255); raw() = rhs; return *this; } Bounded_Reference& operator = (const Bounded_Reference& rhs) { assert(_offset != 255); raw() = rhs.raw(); return *this; } friend std::ostream& operator << (std::ostream& os, const Bounded_Reference< T >& ref) { os << "[bptr=" << static_cast< int >(ref._offset) << ",deref=" << ref.raw() << "]"; return os; } // the copy asop is shallow; we need swap overload to shuffle a vector of references friend void swap(Bounded_Reference& lhs, Bounded_Reference& rhs) { std::swap(lhs._offset, rhs._offset); } private: friend class Bounded_Pointer< T >; Bounded_Reference(Bounded_Pointer< T > bptr) : _offset(bptr._offset) { assert(_offset != 255); } uint8_t _offset; }; // class Bounded_Reference template < typename T > class Bounded_Allocator { public: typedef T value_type; typedef Bounded_Pointer< T > pointer; pointer allocate(size_t n) { assert(inited()); assert(n == 1); pointer p; uint8_t i; for (i = 0; i < 255 and _in_use[i]; ++i); assert(i < 255); p._offset = i; _in_use[p._offset] = true; //std::clog << "allocating node " << static_cast< int >(p._offset) << "\n"; return p; } void deallocate(pointer p, size_t n) { assert(inited()); assert(n == 1); assert(_in_use[p._offset]); //std::clog << "deallocating node " << static_cast< int >(p._offset) << "\n"; _in_use[p._offset] = false; } // static methods static void init() { assert(_in_use.empty()); _in_use = std::vector< bool >(255, false); // allocate non-constructed storage _base = static_cast< T* >(::operator new [] (255 * sizeof(T))); } static bool inited() { return _in_use.size() == 255; } static bool is_clear() { assert(inited()); for (uint8_t i = 0; i < 255; ++i) { if (_in_use[i]) { return false; } } return true; } static void destroy() { // deallocate storage without destructors ::operator delete [] (_base); _in_use.clear(); } private: friend class Bounded_Pointer< T >; friend class Bounded_Pointer< const T >; static T* _base; static std::vector< bool > _in_use; }; // class Bounded_Allocator template < typename T > T* Bounded_Allocator< T >::_base = NULL; template < typename T > std::vector< bool > Bounded_Allocator< T >::_in_use; template < typename T > class Bounded_Reference_Cont : private std::vector< Bounded_Reference< T > > { private: typedef T val_type; typedef std::vector< Bounded_Reference< T > > Base; typedef Bounded_Allocator< T > allocator_type; typedef Bounded_Pointer< T > pointer; public: typedef typename Base::value_type value_type; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reference reference; typedef typename Base::const_reference const_reference; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; iterator begin() { return Base::begin(); } iterator end() { return Base::end(); } const_iterator begin() const { return Base::begin(); } const_iterator end() const { return Base::end(); } reverse_iterator rbegin() { return Base::rbegin(); } reverse_iterator rend() { return Base::rend(); } const_reverse_iterator rbegin() const { return Base::rbegin(); } const_reverse_iterator rend() const { return Base::rend(); } reference front() { return Base::front(); } const_reference front() const { return Base::front(); } reference back() { return Base::back(); } const_reference back() const { return Base::back(); } size_t size() const { return Base::size(); } reference operator [] (size_t i) { return Base::operator [] (i); } const_reference operator [] (size_t i) const { return Base::operator [] (i); } void push_back(const value_type& v) { Base::push_back(v); } Bounded_Reference_Cont(size_t n = 0) : Base(), _allocator() { for (size_t i = 0; i < n; ++i) { pointer p = _allocator.allocate(1); new (p.raw()) val_type(); Base::push_back(*p); } } Bounded_Reference_Cont(const Bounded_Reference_Cont& other) : Base(), _allocator(other._allocator) { //std::clog << "copying values container\n"; *this = other; } template < typename InputIterator > Bounded_Reference_Cont(InputIterator it_start, InputIterator it_end) : Base(), _allocator() { for (InputIterator it = it_start; it != it_end; ++it) { pointer p = _allocator.allocate(1); new (p.raw()) val_type(*it); Base::push_back(*p); } } ~Bounded_Reference_Cont() { clear(); } void clear() { while (not Base::empty()) { pointer p = &Base::back(); p->~val_type(); _allocator.deallocate(p, 1); Base::pop_back(); } } Bounded_Reference_Cont& operator = (const Bounded_Reference_Cont& other) { if (&other != this) { clear(); for (typename Base::const_iterator it = other.begin(); it != other.end(); ++it) { pointer p = _allocator.allocate(1); new (p.raw()) val_type(*it); Base::push_back(*p); } } return *this; } private: allocator_type _allocator; }; // class Bounded_Reference_Cont template < typename T > class Bounded_Pointer_Holder { public: typedef T value_type; typedef Bounded_Pointer< value_type > pointer; typedef Bounded_Pointer< const value_type > const_pointer; typedef Bounded_Allocator< value_type > allocator_type; Bounded_Pointer_Holder() : _ptr(allocator_type().allocate(1)) { new (_ptr.raw()) value_type(); } ~Bounded_Pointer_Holder() { _ptr->~value_type(); allocator_type().deallocate(_ptr, 1); } const_pointer get_node () const { return _ptr; } pointer get_node () { return _ptr; } private: const pointer _ptr; }; // class Bounded_Pointer_Holder namespace boost { namespace intrusive { template < typename T > struct pointer_traits< Bounded_Pointer< T > > { typedef T element_type; typedef Bounded_Pointer< T > pointer; typedef Bounded_Pointer< const T > const_pointer; typedef ptrdiff_t difference_type; typedef Bounded_Reference< T > reference; template struct rebind_pointer { typedef typename Bounded_Pointer< T >::template rebind< U >::type type; }; static pointer pointer_to(reference r) { return &r; } static pointer const_cast_from(const_pointer cptr) { return cptr.unconst(); } }; } // namespace intrusive } // namespace boost template < typename T, typename U > // typename boost::enable_if< boost::is_same< typename boost::remove_const< T >::type, // typename boost::remove_const< U >::type >, int >::type = 42 > bool operator != (const Bounded_Pointer< T >& lhs, const Bounded_Pointer< U >& rhs) { return !(lhs == rhs); } template < typename T > bool operator == (const Bounded_Pointer< T >& lhs, const void* p) { assert(!p); return lhs == Bounded_Pointer< T >(); } template < typename T > bool operator == (const void* p, const Bounded_Pointer< T >& rhs) { assert(!p); return Bounded_Pointer< T >() == rhs; } template < typename T > bool operator != (const Bounded_Pointer< T >& lhs, const void* p) { assert(!p); return lhs != Bounded_Pointer< T >(); } template < typename T > bool operator != (const void* p, const Bounded_Pointer< T >& rhs) { assert(!p); return Bounded_Pointer< T >() != rhs; } #endif