From b1101d64fcc5243106a879fc5e7e6e2e633f70c8 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 16 Sep 2016 16:05:32 +0300 Subject: [PATCH] Add simple explicit placer in C++. --- experiments/placer/Makefile | 16 +++++ experiments/placer/placer.cc | 122 +++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 experiments/placer/Makefile create mode 100644 experiments/placer/placer.cc diff --git a/experiments/placer/Makefile b/experiments/placer/Makefile new file mode 100644 index 00000000000..681bf6c346f --- /dev/null +++ b/experiments/placer/Makefile @@ -0,0 +1,16 @@ +CXX = g++ +CXXFLAGS = -std=c++11 -g2 -Wall -Werror + +all: placer + +run: placer + ./placer + +clean: + rm -f *.o placer + +placer: placer.o + $(CXX) $(CXXFLAGS) -o $@ $< + +placer.o: placer.cc + $(CXX) $(CXXFLAGS) -c $< diff --git a/experiments/placer/placer.cc b/experiments/placer/placer.cc new file mode 100644 index 00000000000..ceb7f14fcd9 --- /dev/null +++ b/experiments/placer/placer.cc @@ -0,0 +1,122 @@ +#include +#include +#include + +#include + +struct Container { + uint8_t* data_; + uint8_t* current_; + int size_; + int ref_count_; + + Container(int size) + : size_(size), ref_count_(1) { + data_ = reinterpret_cast(calloc(size_, 1)); + current_ = data_; + } + + ~Container() { + assert(ref_count_ == 0); + free(data_); + } + + void* Place(int size) { + if (current_ + size > data_ + size_) { + return nullptr; + } + void* result = current_; + current_ += size; + return result; + } + + void AddRef() { + if (data_) { + ref_count_++; + } + } + + void Release() { + if (data_) { + ref_count_--; + } + } + + void Dispose() { + // Destroy container ignoring non-zero refcount. Use with care. + ref_count_ = 0; + free(data_); + data_ = nullptr; + current_ = nullptr; + } +}; + +template +struct Ref { + T* ref_; + Container* container_; + + Ref() : ref_(nullptr), container_(nullptr) {} + Ref(const Ref& other) : ref_(nullptr), container_(nullptr) { + Assign(other); + } + Ref(T* ref, Container* container) : ref_(ref), container_(container) { + if (container_) { + container_->AddRef(); + } + } + ~Ref() { + if (ref_ && container_) { + container_->Release(); + } + } + + static Ref Alloc(Container* container) { + return Ref(reinterpret_cast(container->Place(sizeof(T))), container); + } + + void Assign(const Ref& other) { + if (ref_) { + container_->Release(); + } + container_ = other.container_; + container_->AddRef(); + ref_ = other.ref_; + } + + T* operator->() const { + return ref_; + } + + bool null() const { return ref_ == nullptr; } +}; + +struct List { + Ref next_; + int data_; +}; + +void test_placer() { + printf("Start placement\n"); + Container heap(1024); + + Ref head = Ref::Alloc(&heap); + head->data_ = 1; + Ref cur = head; + for (int i = 0; i < 10; ++i) { + cur->next_ = Ref::Alloc(&heap); + cur = cur->next_; + cur->data_ = i + 2; + } + cur = head; + while (!cur.null()) { + printf("next is %d\n", cur->data_); + cur = cur->next_; + } + + heap.Dispose(); +} + +int main() { + test_placer(); +}