adding yasli
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@215 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
f994398a51
commit
cf4af691c2
7 changed files with 1520 additions and 0 deletions
447
include/loki/yasli/yasli_memory.h
Executable file
447
include/loki/yasli/yasli_memory.h
Executable file
|
@ -0,0 +1,447 @@
|
|||
#ifndef YASLI_MEMORY_H_
|
||||
#define YASLI_MEMORY_H_
|
||||
|
||||
#include "yasli_traits.h"
|
||||
#include "yasli_protocols.h"//!
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <misc/mojo.h>//NOT A SAFE WAY TO INCLUDE IT
|
||||
|
||||
namespace yasli {
|
||||
|
||||
|
||||
// 20.4.1, the default allocator:
|
||||
template <class T> class allocator;
|
||||
template <> class allocator<void>;
|
||||
|
||||
// 20.4.1.2, allocator globals
|
||||
template <class T, class U>
|
||||
bool operator==(const allocator<T>&, const allocator<U>&) throw()
|
||||
{ return true; }
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!=(const allocator<T>&, const allocator<U>&) throw()
|
||||
{ return false; }
|
||||
|
||||
// 20.4.2, raw storage iterator:
|
||||
// @@@ not defined, use the std one @@@
|
||||
//template <class OutputIterator, class T> class raw_storage_iterator;
|
||||
|
||||
// 20.4.3, temporary buffers:
|
||||
// @@@ not defined, use the std one @@@
|
||||
//template <class T>
|
||||
//pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n);
|
||||
// @@@ not defined, use the std one @@@
|
||||
// template <class T>
|
||||
// void return_temporary_buffer(T* p);
|
||||
|
||||
// 20.4.4, specialized algorithms:
|
||||
template <class InputIterator, class ForwardIterator>
|
||||
ForwardIterator
|
||||
uninitialized_copy(InputIterator first, InputIterator last,
|
||||
ForwardIterator result);
|
||||
|
||||
template <class ForwardIterator, class Size, class T>
|
||||
void uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
|
||||
// 20.4.5, pointers:
|
||||
// @@@ not defined, use the std one @@@
|
||||
// template<class X> class auto_ptr;
|
||||
}
|
||||
|
||||
namespace yasli {
|
||||
template <class T> class allocator;
|
||||
// specialize for void:
|
||||
template <> class allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef void* pointer;
|
||||
typedef const void* const_pointer;
|
||||
// reference-to-void members are impossible.
|
||||
typedef void value_type;
|
||||
template <class U> struct rebind { typedef allocator<U> other; };
|
||||
};
|
||||
|
||||
template <class T> class allocator
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template <class U> struct rebind { typedef allocator<U> other; };
|
||||
allocator() throw() {}
|
||||
allocator(const allocator&) throw() {}
|
||||
template <class U> allocator(const allocator<U>&) throw() {}
|
||||
~allocator() throw() {}
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) { return &x; }
|
||||
pointer allocate(size_type n, allocator<void>::const_pointer = 0)
|
||||
{
|
||||
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
void deallocate(pointer p, size_type)
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
size_type max_size() const throw()
|
||||
{
|
||||
return size_type(-1);
|
||||
}
|
||||
void construct(pointer p, const T& val)
|
||||
{
|
||||
new((void *) p) T(val);
|
||||
}
|
||||
void destroy(pointer p)
|
||||
{
|
||||
((T*) p)->~T();
|
||||
}
|
||||
};
|
||||
} // namespace yasli
|
||||
|
||||
namespace yasli_nstd
|
||||
{
|
||||
template <class T> class mallocator
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template <class U> struct rebind { typedef mallocator<U> other; };
|
||||
mallocator() throw() {}
|
||||
mallocator(const mallocator&) throw() {}
|
||||
template <class U> mallocator(const mallocator<U>&) throw() {}
|
||||
~mallocator() throw() {}
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) { return &x; }
|
||||
pointer allocate(size_type n, yasli::allocator<void>::const_pointer = 0)
|
||||
{
|
||||
return static_cast<pointer>(malloc(n * sizeof(T)));
|
||||
}
|
||||
void deallocate(pointer p, size_type)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
size_type max_size() const throw()
|
||||
{
|
||||
return size_type(-1);
|
||||
}
|
||||
void construct(pointer p, const T& val)
|
||||
{
|
||||
new((void *) p) T(val);
|
||||
}
|
||||
void destroy(pointer p)
|
||||
{
|
||||
((T*) p)->~T();
|
||||
}
|
||||
};
|
||||
|
||||
//--------------destroy--------
|
||||
|
||||
namespace _impl
|
||||
{
|
||||
struct non_destroyer
|
||||
{
|
||||
template <class A, class T>
|
||||
static void destroy(A& a, T* p, typename A::size_type n) {}
|
||||
|
||||
template <class ForwardIterator>
|
||||
static void destroy_range(ForwardIterator b, ForwardIterator e) {}
|
||||
};
|
||||
|
||||
struct destroyer
|
||||
{
|
||||
template <class A, class T>
|
||||
static void destroy(A& a, T* p, typename A::size_type n)
|
||||
{
|
||||
const typename A::pointer p1 = p + n;
|
||||
for (; p < p1; ++p) a.destroy(p);
|
||||
}
|
||||
|
||||
template <class ForwardIterator>
|
||||
static void destroy_range(ForwardIterator b, ForwardIterator e)
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type
|
||||
value_type;
|
||||
for (; b != e; ++b) (*b).~value_type();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class A, class T>
|
||||
void destroy(A& a, T* p, typename A::size_type n)
|
||||
{
|
||||
yasli_nstd::type_selector<yasli_nstd::is_class<T>::value != 0,
|
||||
_impl::destroyer,
|
||||
_impl::non_destroyer
|
||||
>::result::destroy(a, p, n);
|
||||
}
|
||||
|
||||
template <class ForwardIterator>
|
||||
void destroy_range(ForwardIterator b, ForwardIterator e)
|
||||
{
|
||||
yasli_nstd::type_selector<
|
||||
yasli_nstd::is_class<typename std::iterator_traits<ForwardIterator>
|
||||
::value_type>::value != 0,
|
||||
_impl::destroyer,
|
||||
_impl::non_destroyer
|
||||
>::result::destroy_range(b, e);
|
||||
}
|
||||
|
||||
//---------------
|
||||
|
||||
|
||||
template <class It1, class It2>
|
||||
It2 uninitialized_move(It1 b, It1 e, It2 d)
|
||||
{
|
||||
return mojo::uninitialized_move(b, e, d);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
struct generic_allocator_traits
|
||||
{
|
||||
static typename A::pointer
|
||||
reallocate(
|
||||
A& a,
|
||||
typename A::pointer b,
|
||||
typename A::pointer e,
|
||||
typename A::size_type newSize)
|
||||
{
|
||||
typename A::pointer p1 = a.allocate(newSize, b);
|
||||
const typename A::size_type oldSize = e - b;
|
||||
if (oldSize <= newSize) // expand
|
||||
{
|
||||
yasli_protocols::move_traits<typename A::value_type>::destructive_move(
|
||||
b, b + oldSize, p1);
|
||||
}
|
||||
else // shrink
|
||||
{
|
||||
yasli_protocols::move_traits<typename A::value_type>::destructive_move(
|
||||
b, b + newSize, p1);
|
||||
yasli_nstd::destroy(a, b + newSize, oldSize - newSize);
|
||||
}
|
||||
a.deallocate(b, oldSize);
|
||||
return p1;
|
||||
}
|
||||
|
||||
static bool reallocate_inplace(
|
||||
A& a,
|
||||
typename A::pointer b,
|
||||
typename A::size_type newSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
generic_allocator_traits();
|
||||
};
|
||||
|
||||
template <class A>
|
||||
struct allocator_traits : public generic_allocator_traits<A>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct allocator_traits< yasli::allocator<T> >
|
||||
: public generic_allocator_traits< yasli::allocator<T> >
|
||||
{
|
||||
#if YASLI_NEW_IS_MALLOC != 0
|
||||
|
||||
static bool reallocate_inplace(
|
||||
A& a,
|
||||
typename A::pointer b,
|
||||
typename A::size_type newSize)
|
||||
{
|
||||
allocator_traits< yasli_nstd::mallocator<T> >
|
||||
::reallocate_inplace(a, b, newSize);
|
||||
}
|
||||
|
||||
static typename yasli::allocator<T>::pointer
|
||||
reallocate(
|
||||
yasli::allocator<T>& a,
|
||||
typename yasli::allocator<T>::pointer b,
|
||||
typename yasli::allocator<T>::pointer e,
|
||||
typename yasli::allocator<T>::size_type newSize)
|
||||
{
|
||||
allocator_traits< yasli_nstd::mallocator<T> >
|
||||
::reallocate(a, b, e, newSize);
|
||||
}
|
||||
#endif//yasli_new_is_malloc
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct allocator_traits< yasli_nstd::mallocator<T> >
|
||||
: public generic_allocator_traits< yasli_nstd::mallocator<T> >
|
||||
{
|
||||
#if YASLI_HAS_EXPAND && YASLI_HAS_EFFICIENT_MSIZE
|
||||
static bool reallocate_inplace(
|
||||
yasli_nstd::mallocator<T>& a,
|
||||
typename yasli_nstd::mallocator<T>::pointer b,
|
||||
typename yasli_nstd::mallocator<T>::size_type newSize)
|
||||
{
|
||||
if (b == 0) return malloc(newSize);
|
||||
if (newSize == 0) {free(b); return false;}
|
||||
return b == yasli_platform::expand(b, newSize)
|
||||
&& yasli_platform::msize(b) >= newSize;
|
||||
}
|
||||
#endif
|
||||
static typename yasli_nstd::mallocator<T>::pointer
|
||||
reallocate(
|
||||
yasli_nstd::mallocator<T>& a,
|
||||
typename yasli_nstd::mallocator<T>::pointer b,
|
||||
typename yasli_nstd::mallocator<T>::pointer e,
|
||||
typename yasli_nstd::mallocator<T>::size_type newSize)
|
||||
{
|
||||
if (yasli_nstd::is_memmoveable<T>::value)
|
||||
{
|
||||
return static_cast<T*>(realloc(b, newSize));
|
||||
}
|
||||
if(reallocate_inplace(a, b, newSize)) return b;
|
||||
return generic_allocator_traits< yasli_nstd::mallocator<T> >::
|
||||
reallocate(a, b, e, newSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace yasli
|
||||
{
|
||||
//Here is where type_selector is really much more ugly than
|
||||
//enable_if.
|
||||
|
||||
//----------------UNINIT COPY--------
|
||||
namespace _impl
|
||||
{
|
||||
//safe
|
||||
template <class InputItr, class FwdItr>
|
||||
struct uninitialized_safe_copier
|
||||
{
|
||||
static FwdItr execute(InputItr first, InputItr last, FwdItr result)
|
||||
{
|
||||
//
|
||||
struct ScopeGuard
|
||||
{
|
||||
FwdItr begin;
|
||||
FwdItr* current;
|
||||
~ScopeGuard()
|
||||
{
|
||||
if (!current) return;
|
||||
FwdItr end = *current;
|
||||
typedef typename std::iterator_traits<FwdItr>::value_type T;
|
||||
for (; begin != end; ++begin) (&*begin)->~T();
|
||||
}
|
||||
} guard = { result, &result };
|
||||
for (; first != last; ++first, ++result)
|
||||
new(&*result) typename std::iterator_traits<FwdItr>::value_type(*first);
|
||||
// commit
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct uninitialized_memcopier
|
||||
{
|
||||
static T* execute(const T* first, const T* last, T* result)
|
||||
{
|
||||
yasli_nstd::is_memcopyable<T>::value;
|
||||
const size_t s = last - first;
|
||||
memmove(result, first, s * sizeof(T));
|
||||
return result + s;
|
||||
}
|
||||
};
|
||||
|
||||
}// _impl
|
||||
|
||||
// @@@ TODO: specialize for yasli_nstd::fill_iterator
|
||||
|
||||
template <class InputItr, class FwdItr>
|
||||
FwdItr uninitialized_copy(InputItr first, InputItr last, FwdItr result)
|
||||
{
|
||||
std::cout<<"neither\n";
|
||||
return _impl::uninitialized_safe_copier<InputItr, FwdItr>::execute(first, last, result);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* uninitialized_copy(const T* first, const T* last, T* result)
|
||||
{
|
||||
std::cout<<"const\n";
|
||||
return yasli_nstd::type_selector<yasli_nstd::is_memcopyable<T>::value != 0,
|
||||
_impl::uninitialized_memcopier<T>,
|
||||
_impl::uninitialized_safe_copier<const T*, T*>
|
||||
>::result::execute(first, last, result);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* uninitialized_copy(T* first, T* last, T* result)
|
||||
{
|
||||
std::cout<<"non-const\n";
|
||||
return uninitialized_copy(static_cast<const T*>(first),
|
||||
static_cast<const T*>(last), result);
|
||||
}
|
||||
|
||||
//-------------------------UNINIT FILL------
|
||||
|
||||
template <class ForwardIterator, class T>
|
||||
void
|
||||
uninitialized_fill(ForwardIterator first, ForwardIterator last,
|
||||
const T& x)
|
||||
{
|
||||
struct ScopeGuard
|
||||
{
|
||||
ForwardIterator first;
|
||||
ForwardIterator* pCrt;
|
||||
~ScopeGuard()
|
||||
{
|
||||
if (pCrt) yasli_nstd::destroy_range(first, *pCrt);
|
||||
}
|
||||
} guard = { first, &first };
|
||||
for (; first != last; ++first)
|
||||
new(&*first) T(x);
|
||||
// Commit
|
||||
guard.pCrt = 0;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void
|
||||
uninitialized_fill(T* first, T* last, const U& x)
|
||||
{
|
||||
struct ScopeGuard
|
||||
{
|
||||
T* first;
|
||||
T** pCrt;
|
||||
~ScopeGuard()
|
||||
{
|
||||
if (pCrt) yasli_nstd::destroy_range(first, *pCrt);
|
||||
}
|
||||
} guard = { first, &first };
|
||||
assert(first <= last);
|
||||
switch ((last - first) & 7u)
|
||||
{
|
||||
case 0:
|
||||
while (first != last)
|
||||
{
|
||||
new(first) T(x); ++first;
|
||||
case 7: new(first) T(x); ++first;
|
||||
case 6: new(first) T(x); ++first;
|
||||
case 5: new(first) T(x); ++first;
|
||||
case 4: new(first) T(x); ++first;
|
||||
case 3: new(first) T(x); ++first;
|
||||
case 2: new(first) T(x); ++first;
|
||||
case 1: new(first) T(x); ++first;
|
||||
assert(first <= last);
|
||||
}
|
||||
}
|
||||
// Commit
|
||||
guard.pCrt = 0;
|
||||
}
|
||||
|
||||
}// yasli
|
||||
|
||||
#endif // YASLI_MEMORY_H_
|
Loading…
Add table
Add a link
Reference in a new issue