#include <time.h>
#include <set>
#include <iostream>
#include <functional>
#include <vector>
#include <cstddef>
#include <cstdlib>
#include <limits>
#include <new>
namespace block_allocator {
template <class T, unsigned N = 32>
class block_allocator {
void** blocks;
void** free_blocks;
int allocated;
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 block_allocator<U, N> other;
};
block_allocator()
: blocks()
, free_blocks()
, allocated()
{
}
template<class U, unsigned M>
block_allocator(const block_allocator<U, M>&)
: blocks()
, free_blocks()
, allocated()
{
}
~block_allocator()
{
while (blocks) {
void** next = reinterpret_cast<void**>(*blocks);
free(blocks - block_elements);
blocks = next;
}
}
pointer address(reference x) const
{
return &x;
}
const_pointer address(const_reference x) const
{
return &x;
}
pointer allocate(size_type n, const void* = 0)
{
if (n == 1) {
if (free_blocks) {
pointer result = reinterpret_cast<pointer>(free_blocks);
free_blocks = reinterpret_cast<void**>(*free_blocks);
return result;
} else {
void** new_block = do_alloc<void*>(area_size);
new_block[block_elements] = blocks;
blocks = &new_block[block_elements];
new_block[(N - 1) * multiplier] = 0;
for (size_type i = 2; i < N; ++i) {
new_block[(i - 1) * multiplier] =
&new_block[i * multiplier];
}
free_blocks = &new_block[multiplier];
return reinterpret_cast<pointer>(new_block);
}
} else {
return do_alloc<T>(n * sizeof(T));
}
}
void deallocate(pointer p, size_type n)
{
if (n == 1) {
*reinterpret_cast<void**>(p) = free_blocks;
free_blocks = reinterpret_cast<void**>(p);
} else {
free(p);
}
}
size_type max_size() const
{
return std::numeric_limits<size_type>::max();
}
void construct(pointer p, const T& val)
{
new(p) T(val);
}
void destroy(pointer p)
{
p->~T();
}
private:
template <class U>
static U* do_alloc(size_type n) {
U* result = reinterpret_cast<U*>(malloc(n));
if (result) {
return result;
} else {
throw std::bad_alloc();
}
}
static char check[sizeof(T) % sizeof(void*) == 0 ? 1 : -1];
static const size_type multiplier = sizeof(T) / sizeof(void*);
static const size_type block_elements = multiplier * N;
static const size_type area_size = sizeof(T) * N + sizeof(void*);
};
}
std::vector<int> input;
template <class Cont>
void do_test()
{
Cont c;
for (std::vector<int>::const_iterator iter = input.begin(), end = input.end(); iter != end; ++iter) {
c.insert(*iter);
}
}
int main()
{
typedef void (*test)();
test t[] = {
do_test<std::set<int> >,
do_test<std::set<int, std::less<int>, block_allocator::block_allocator<int, 1024> > >
};
int size = 1000000;
for (int i = 0; i < size; ++i) {
input.push_back(i + i % 3);
}
size = sizeof t / sizeof t[0];
for (int i = 0; i < size; ++i) {
const clock_t begin = clock();
t[i]();
std::cout << clock() - begin << std::endl;
}
}