Reference is single value.

This commit is contained in:
Nikolay Igotti
2016-09-16 18:01:52 +03:00
parent b1101d64fc
commit 1a174c118e
+65 -40
View File
@@ -4,12 +4,14 @@
#include <cassert> #include <cassert>
struct Container { class Container {
private:
uint8_t* data_; uint8_t* data_;
uint8_t* current_; uint8_t* current_;
int size_; int size_;
int ref_count_; int ref_count_;
public:
Container(int size) Container(int size)
: size_(size), ref_count_(1) { : size_(size), ref_count_(1) {
data_ = reinterpret_cast<uint8_t*>(calloc(size_, 1)); data_ = reinterpret_cast<uint8_t*>(calloc(size_, 1));
@@ -22,22 +24,26 @@ struct Container {
} }
void* Place(int size) { void* Place(int size) {
size += sizeof(Container*);
if (current_ + size > data_ + size_) { if (current_ + size > data_ + size_) {
return nullptr; return nullptr;
} }
void* result = current_; Container** result = reinterpret_cast<Container**>(current_);
*result = this;
current_ += size; current_ += size;
return result; return result;
} }
void AddRef() { void AddRef() {
if (data_) { if (data_) {
//printf("addref %d\n", ref_count_);
ref_count_++; ref_count_++;
} }
} }
void Release() { void Release() {
if (data_) { if (data_) {
// printf("release %d\n", ref_count_);
ref_count_--; ref_count_--;
} }
} }
@@ -52,43 +58,61 @@ struct Container {
}; };
template <class T> template <class T>
struct Ref { class Ref {
T* ref_; private:
Container* container_; void* ptr_;
Ref() : ref_(nullptr), container_(nullptr) {} explicit Ref(void* ptr) : ptr_(ptr) {
Ref(const Ref& other) : ref_(nullptr), container_(nullptr) { if (ptr_) {
container()->AddRef();
}
}
public:
Ref() : ptr_(nullptr) {}
Ref(const Ref& other) : ptr_(nullptr) {
Assign(other); Assign(other);
} }
Ref(T* ref, Container* container) : ref_(ref), container_(container) { Ref& operator=(const Ref& other) {
if (container_) { Assign(other);
container_->AddRef(); return *this;
}
} }
~Ref() { ~Ref() {
if (ref_ && container_) { if (ptr_) {
container_->Release(); container()->Release();
} }
} }
static Ref<T> Alloc(Container* container) { T* ref() const {
return Ref<T>(reinterpret_cast<T*>(container->Place(sizeof(T))), container); if (!ptr_) return nullptr;
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(ptr_) + sizeof(Container*));
}
Container* container() {
return *reinterpret_cast<Container**>(ptr_);
} }
void Assign(const Ref<T>& other) { void Assign(const Ref<T>& other) {
if (ref_) { // TODO: optimize for an important case where containers matches.
container_->Release(); if (ptr_) {
container()->Release();
}
ptr_ = other.ptr_;
if (ptr_) {
container()->AddRef();
} }
container_ = other.container_;
container_->AddRef();
ref_ = other.ref_;
} }
T* operator->() const { T* operator->() const {
return ref_; return ref();
} }
bool null() const { return ref_ == nullptr; } bool null() const { return ptr_ == nullptr; }
static Ref<T> Alloc(Container* container) {
return Ref<T>(container->Place(sizeof(T)));
}
}; };
struct List { struct List {
@@ -99,24 +123,25 @@ struct List {
void test_placer() { void test_placer() {
printf("Start placement\n"); printf("Start placement\n");
Container heap(1024); Container heap(1024);
{
Ref<List> head = Ref<List>::Alloc(&heap); Ref<List> head = Ref<List>::Alloc(&heap);
head->data_ = 1; head->data_ = 1;
Ref<List> cur = head; Ref<List> cur = head;
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
cur->next_ = Ref<List>::Alloc(&heap); cur->next_ = Ref<List>::Alloc(&heap);
cur = cur->next_; cur = cur->next_;
cur->data_ = i + 2; cur->data_ = i + 2;
}
cur = head;
while (!cur.null()) {
printf("next is %d\n", cur->data_);
cur = cur->next_;
}
} }
cur = head;
while (!cur.null()) {
printf("next is %d\n", cur->data_);
cur = cur->next_;
}
heap.Dispose(); heap.Dispose();
} }
int main() { int main() {
test_placer(); test_placer();
return 0;
} }