Last active
October 18, 2018 12:30
-
-
Save matovitch/9104b8fb824e563eebdd5d3bcacde832 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://coliru.stacked-crooked.com/a/79b95603bd598fc4 | |
// http://coliru.stacked-crooked.com/a/329eb69e036b8d4b | |
// http://coliru.stacked-crooked.com/a/3a4c06d979ae966c | |
// http://coliru.stacked-crooked.com/a/e81b99fdd5e2b596 | |
#include <type_traits> | |
#include <iostream> | |
#include <utility> | |
#include <cstdint> | |
#include <vector> | |
#include <cmath> | |
namespace buffer | |
{ | |
template <class Type> | |
struct TAbstract | |
{ | |
virtual TAbstract<Type>* makeNext () const = 0; | |
virtual Type* push () = 0; | |
virtual Type* pop () = 0; | |
virtual void clean () = 0; | |
virtual ~TAbstract() {} | |
}; | |
} // namespace buffer | |
template <class Type, std::size_t SIZE> | |
class TBuffer : public buffer::TAbstract<Type> | |
{ | |
public: | |
TBuffer() : | |
_head{reinterpret_cast<Type*>(&_memory)}, | |
_base{reinterpret_cast<Type*>(&_memory)}, | |
_tail{reinterpret_cast<Type*>(&_memory) + SIZE} | |
{ | |
std::cout << "memory: " << sizeof(decltype(_memory)) << " " << &_memory << std::endl; | |
std::cout << "PLOP: " << sizeof(Type) * SIZE << std::endl; | |
std::cout << "head: " << _head << std::endl; | |
std::cout << "tail: " << _tail << std::endl; | |
} | |
Type* push() override | |
{ | |
if (_head == _tail) | |
{ | |
return nullptr; | |
} | |
return _head++; | |
} | |
Type* pop() override | |
{ | |
if (_head == _base) | |
{ | |
return nullptr; | |
} | |
return --_head; | |
} | |
buffer::TAbstract<Type>* makeNext() const override | |
{ | |
return new TBuffer<Type, std::min(SIZE << 1, static_cast<std::size_t>(0x10000))>; | |
} | |
void clean() override | |
{ | |
Type* headPtr = _base; | |
while (headPtr != _head) | |
{ | |
headPtr->~Type(); | |
headPtr++; | |
} | |
} | |
private: | |
Type* _head = nullptr; | |
Type* const _base; | |
const Type* const _tail; | |
std::aligned_storage_t<sizeof(Type) * SIZE, alignof(Type)> _memory; | |
}; | |
template <class FactoryTraits> | |
class TFactory | |
{ | |
using Type = typename FactoryTraits::Type; | |
using StackBuffer = typename FactoryTraits::StackBuffer; | |
using AbstractBuffer = typename FactoryTraits::AbstractBuffer; | |
public: | |
TFactory() | |
{ | |
std::cout << "stack: " << sizeof(decltype(_stack)) << " " << &_stack << std::endl; | |
_buffers.emplace_back(&_stack); | |
} | |
template <class... Args> | |
Type* make(Args&&... args) | |
{ | |
Type* const ptr = _buffers.back()->push(); | |
if (!ptr) | |
{ | |
if (_recycleds.empty()) | |
{ | |
_buffers.emplace_back(_buffers.back()->makeNext()); | |
return make(args...); | |
} | |
AbstractBuffer* const bufferPtr = _recycleds.back(); | |
_buffers.emplace_back(bufferPtr); | |
_recycleds.pop_back(); | |
return make(args...); | |
} | |
std::cout << ptr << " " << &_buffers << std::endl; | |
new(static_cast<void*>(ptr)) Type(std::forward<Args>(args)...); | |
return ptr; | |
} | |
void destroy(Type* ptr) | |
{ | |
AbstractBuffer* const backBuffer = _buffers.back(); | |
Type* pop = backBuffer->pop(); | |
std::cout << "backBuffer, pop: " << backBuffer << " " << pop << std::endl; | |
if (!pop) | |
{ | |
std::cout << "HAHA !" << std::endl; | |
if (backBuffer == &_stack) | |
{ | |
std::cout << "HAHA !" << std::endl; | |
ptr->~Type(); | |
return; | |
} | |
_recycleds.emplace_back(backBuffer); | |
_buffers.pop_back(); | |
return destroy(ptr); | |
} | |
ptr->~Type(); | |
new(static_cast<void*>(ptr)) Type(std::move(*pop)); | |
} | |
void clean() | |
{ | |
for (AbstractBuffer* buffer : _buffers) | |
{ | |
buffer->clean(); | |
if (buffer == &_stack) | |
{ | |
continue; | |
} | |
delete buffer; | |
} | |
for (AbstractBuffer* buffer : _recycleds) | |
{ | |
delete buffer; | |
} | |
_buffers.clear(); | |
} | |
~TFactory() | |
{ | |
clean(); | |
} | |
private: | |
StackBuffer _stack; | |
std::vector<AbstractBuffer*> _buffers; | |
std::vector<AbstractBuffer*> _recycleds; | |
}; | |
namespace factory | |
{ | |
template <class FactoryType, std::size_t LOG2_STACK_SIZE> | |
struct TTraits | |
{ | |
using Type = FactoryType; | |
using StackBuffer = TBuffer<Type, 1 << LOG2_STACK_SIZE>; | |
using AbstractBuffer = buffer::TAbstract<Type>; | |
}; | |
} // namespace factory | |
template <class MyContainerTraits> | |
class TMyContainer | |
{ | |
using Factory = typename MyContainerTraits::Factory; | |
using Type = typename MyContainerTraits::Type; | |
public: | |
template <class... Args> | |
Type* emplace_back(Args&&... args) | |
{ | |
return _back = _factory.make(args...); | |
} | |
void erase(Type* ptr) | |
{ | |
_factory.destroy(ptr); | |
} | |
private: | |
Type* _back; | |
Factory _factory; | |
}; | |
namespace myContainer | |
{ | |
template <class MyContainerType, std::size_t LOG2_STACK_SIZE> | |
struct TTraits | |
{ | |
using Type = MyContainerType; | |
using FactoryTraits = factory::TTraits<Type, LOG2_STACK_SIZE>; | |
using Factory = TFactory<FactoryTraits>; | |
}; | |
} // namespace myContainer | |
int main() | |
{ | |
using MyContainerTraits = myContainer::TTraits<int, 2>; | |
using MyContainer = TMyContainer<MyContainerTraits>; | |
MyContainer myContainer; | |
int* intPtr1 = myContainer.emplace_back(42); | |
int* intPtr2 = myContainer.emplace_back(43); | |
int* intPtr3 = myContainer.emplace_back(44); | |
int* intPtr4 = myContainer.emplace_back(45); | |
int* intPtr5 = myContainer.emplace_back(46); | |
std::cout << intPtr1 << std::endl; | |
std::cout << intPtr2 << std::endl; | |
std::cout << intPtr3 << std::endl; | |
std::cout << intPtr4 << std::endl; | |
std::cout << intPtr5 << std::endl; | |
myContainer.erase(intPtr1); | |
myContainer.erase(intPtr2); | |
myContainer.erase(intPtr3); | |
myContainer.erase(intPtr4); | |
myContainer.erase(intPtr5); | |
return *intPtr1; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment