Pointers!

This commit is contained in:
2023-10-21 19:04:49 +02:00
parent a2c05c4b7b
commit 4f975238ea
2 changed files with 160 additions and 163 deletions

View File

@@ -1,108 +1,111 @@
#ifndef POINTERS_H
#define POINTERS_H
namespace SUSTL {
class SharedPtrTester;
#include <utility>
template<typename T>
class SharedPtr {
friend SharedPtrTester;
public:
SharedPtr() = default;
#include "kmem.hpp"
SharedPtr(T *data) : ptr(data), uses(new int(1)) {}
class SharedPtrTester;
~SharedPtr() {
if (ptr == nullptr || uses == nullptr) return;
--(*uses);
if (*uses == 0) {
delete ptr;
delete uses;
}
template<typename T>
class SharedPtr {
friend SharedPtrTester;
public:
SharedPtr() = default;
SharedPtr(T *data) : ptr(data), uses(new int(1)) {}
~SharedPtr() {
if (ptr == nullptr || uses == nullptr) return;
--(*uses);
if (*uses == 0) {
delete ptr;
delete uses;
}
}
SharedPtr(SharedPtr const &other) : ptr(other.ptr), uses(other.uses) {
++(*uses);
SharedPtr(SharedPtr const &other) : ptr(other.ptr), uses(other.uses) {
++(*uses);
}
SharedPtr(SharedPtr &&other) {
uses = other.uses;
ptr = other.ptr;
other.uses = nullptr;
other.ptr = nullptr;
}
SharedPtr &operator=(SharedPtr other) {
std::swap(ptr, other.ptr);
std::swap(uses, other.uses);
return *this;
}
T *operator->() const { return ptr; }
T &operator*() const { return *ptr; }
T *get() const noexcept { return ptr; }
int useCount() const { return *uses; }
private:
T *ptr = nullptr;
int *uses = nullptr;
};
class COWTester;
template<typename T>
class COWPointer {
private:
friend COWTester;
SharedPtr<T> ptr;
void copy() {
if (ptr.get() && ptr.useCount() > 1) {
ptr = SharedPtr<T>(new T(*ptr));
}
}
SharedPtr(SharedPtr &&other) {
uses = other.uses;
ptr = other.ptr;
other.uses = nullptr;
other.ptr = nullptr;
}
public:
COWPointer() = default;
SharedPtr &operator=(SharedPtr other) {
std::swap(ptr, other.ptr);
std::swap(uses, other.uses);
return *this;
}
COWPointer(T *data) : ptr(data) {}
T *operator->() const { return ptr; }
COWPointer(SharedPtr<T> data) : ptr(std::move(data)) {}
T &operator*() const { return *ptr; }
COWPointer(COWPointer &&other) = default;
T *get() const noexcept { return ptr; }
COWPointer(COWPointer const &data) = default;
int useCount() const { return *uses; }
COWPointer &operator=(COWPointer other) {
std::swap(ptr, other.ptr);
return *this;
}
private:
T *ptr = nullptr;
int *uses = nullptr;
};
~COWPointer() = default;
class COWTester;
T *get() const {
return ptr.get();
}
template<typename T>
class COWPointer {
private:
friend COWTester;
SharedPtr<T> ptr;
T *getRW() {
copy();
return ptr.get();
}
void copy() {
if (ptr.get() && ptr.useCount() > 1) {
ptr = SharedPtr<T>(new T(*ptr));
}
}
int useCount() { return ptr.useCount(); };
public:
COWPointer() = default;
const T &operator*() const {
return *ptr;
}
COWPointer(T *data) : ptr(data) {}
const T *operator->() const {
return ptr.operator->();
}
};
COWPointer(SharedPtr<T> data) : ptr(std::move(data)) {}
COWPointer(COWPointer &&other) = default;
COWPointer(COWPointer const &data) = default;
COWPointer &operator=(COWPointer other) {
std::swap(ptr, other.ptr);
return *this;
}
~COWPointer() = default;
T *get() const {
return ptr.get();
}
T *getRW() {
copy();
return ptr.get();
}
int useCount() { return ptr.useCount(); };
const T &operator*() const {
return *ptr;
}
const T *operator->() const {
return ptr.operator->();
}
};
}
#endif

View File

@@ -5,6 +5,7 @@
#include "TestTemplates.hpp"
#include "PointersCollection.hpp"
#include "SkipList.hpp"
#include "SkipListSet.hpp"
#include "String.hpp"
@@ -13,82 +14,75 @@
#include "tty.hpp"
//#include "String.hpp"
//#include "String.hpp"
class SharedPtrTester {
private:
auto getThingy() {
return SharedPtr<Vector<String>>(
new Vector<String>{"Thingy1", "Thingy2", "Thingy3"});
}
//template<typename T>
//std::string toString(const T &x) {
// std::ostringstream oss;
// oss << x;
// return oss.str();
//}
//
//class SharedPtrTester {
//private:
// auto getThingy() {
// return SharedPtr<Vector<String>>(
// new Vector<String>{"Thingy1", "Thingy2", "Thingy3"});
// }
//
//public:
// bool test() {
// SharedPtr<Vector<String>> test1(
// new Vector<String>{"hello1", "hello2", "hello3"});
// SharedPtr<Vector<String>> test2(getThingy());
// assert((*test2 == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
// auto test22 = test2;
// auto test12 = test1;
// test12->emplace_back("hello4");
// assert((*test1)[3] == "hello4");
// test22->erase(2);
// assert(test2->size() == 2);
// assert((*test2)[1] == "Thingy2");
// return true;
// }
//};
//
//class COWTester {
//private:
// auto getThingy() const {
// return COWPointer<Vector<String>>(
// new Vector<String>{"Thingy1", "Thingy2", "Thingy3"});
// }
//
//public:
// bool test() const {
// COWPointer<Vector<String>> test1(
// new Vector<String>{"hello1", "hello2", "hello3"});
// COWPointer<Vector<String>> test2(getThingy());
// assert((*test2.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
//
// auto test22 = test2;
// auto test12 = test1;
//
// assert(test12.ptr.get() == test1.ptr.get());
// assert(test22.ptr.get() == test2.ptr.get());
// assert((*test2.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
// assert((*test22.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
// assert((*test1.get() == Vector<String>{"hello1", "hello2", "hello3"}));
// assert((*test12.get() == Vector<String>{"hello1", "hello2", "hello3"}));
// assert(test12.ptr.get() == test1.ptr.get());
// assert(test22.ptr.get() == test2.ptr.get());
//
// test12.getRW()->emplace_back("hello4");
// assert(test1.get()->size() == 3);
// assert(test12.get()->size() == 4);
// assert((*test12.get())[3] == "hello4");
// test22.getRW()->erase(2);
// assert(test2.get()->size() == 3);
// assert(test22.get()->size() == 2);
// assert((*test22.get())[1] == "Thingy2");
// assert((*test2.get())[1] == "Thingy2");
//
// assert(test12.ptr.get() != test1.ptr.get());
// assert(test22.ptr.get() != test2.ptr.get());
//
// return true;
// }
//};
public:
bool test() {
SharedPtr<Vector<String>> test1(
new Vector<String>{"hello1", "hello2", "hello3"});
SharedPtr<Vector<String>> test2(getThingy());
assert((*test2 == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
auto test22 = test2;
auto test12 = test1;
test12->emplace_back("hello4");
assert((*test1)[3] == "hello4");
test22->erase(2);
assert(test2->size() == 2);
assert((*test2)[1] == "Thingy2");
all_tty_putstr("SharedPtr tests ok!\n");
return true;
}
};
class COWTester {
private:
auto getThingy() const {
return COWPointer<Vector<String>>(
new Vector<String>{"Thingy1", "Thingy2", "Thingy3"});
}
public:
bool test() const {
COWPointer<Vector<String>> test1(
new Vector<String>{"hello1", "hello2", "hello3"});
COWPointer<Vector<String>> test2(getThingy());
assert((*test2.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
auto test22 = test2;
auto test12 = test1;
assert(test12.ptr.get() == test1.ptr.get());
assert(test22.ptr.get() == test2.ptr.get());
assert((*test2.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
assert((*test22.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
assert((*test1.get() == Vector<String>{"hello1", "hello2", "hello3"}));
assert((*test12.get() == Vector<String>{"hello1", "hello2", "hello3"}));
assert(test12.ptr.get() == test1.ptr.get());
assert(test22.ptr.get() == test2.ptr.get());
test12.getRW()->emplace_back("hello4");
assert(test1.get()->size() == 3);
assert(test12.get()->size() == 4);
assert((*test12.get())[3] == "hello4");
test22.getRW()->erase(2);
assert(test2.get()->size() == 3);
assert(test22.get()->size() == 2);
assert((*test22.get())[1] == "Thingy2");
assert((*test2.get())[1] == "Thingy2");
assert(test12.ptr.get() != test1.ptr.get());
assert(test22.ptr.get() != test2.ptr.get());
all_tty_putstr("COWPointer tests ok!\n");
return true;
}
};
class VectorTester {
public:
@@ -220,9 +214,9 @@ int test_templates() {
stringTester.test();
VectorTester vectorTester;
vectorTester.test();
// SharedPtrTester sharedPtrTester;
// sharedPtrTester.test();
// COWTester cowTester;
// cowTester.test();
SharedPtrTester sharedPtrTester;
sharedPtrTester.test();
COWTester cowTester;
cowTester.test();
return 0;
}