Reference is single value.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user