|
@@ -2,6 +2,8 @@
|
|
|
|
|
|
|
|
#include "common.h"
|
|
#include "common.h"
|
|
|
|
|
|
|
|
|
|
+struct PyObject;
|
|
|
|
|
+
|
|
|
namespace pkpy{
|
|
namespace pkpy{
|
|
|
template<typename T>
|
|
template<typename T>
|
|
|
struct SpAllocator {
|
|
struct SpAllocator {
|
|
@@ -21,22 +23,38 @@ namespace pkpy{
|
|
|
int* counter;
|
|
int* counter;
|
|
|
|
|
|
|
|
inline T* _t() const {
|
|
inline T* _t() const {
|
|
|
- if(is_tagged()) UNREACHABLE();
|
|
|
|
|
|
|
+ if constexpr(std::is_same_v<T, PyObject>){
|
|
|
|
|
+ if(is_tagged()) UNREACHABLE();
|
|
|
|
|
+ }
|
|
|
return (T*)(counter + 1);
|
|
return (T*)(counter + 1);
|
|
|
}
|
|
}
|
|
|
- inline void _inc_counter() const { if(counter) ++(*counter); }
|
|
|
|
|
- inline void _dec_counter() const { if(counter && --(*counter) == 0){ SpAllocator<T>::dealloc(counter); } }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ inline void _inc_counter() const {
|
|
|
|
|
+ if constexpr(std::is_same_v<T, PyObject>){
|
|
|
|
|
+ if(is_tagged()) return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(counter) ++(*counter);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ inline void _dec_counter() const {
|
|
|
|
|
+ if constexpr(std::is_same_v<T, PyObject>){
|
|
|
|
|
+ if(is_tagged()) return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(counter && --(*counter) == 0){
|
|
|
|
|
+ SpAllocator<T>::dealloc(counter);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
public:
|
|
public:
|
|
|
shared_ptr() : counter(nullptr) {}
|
|
shared_ptr() : counter(nullptr) {}
|
|
|
shared_ptr(int* counter) : counter(counter) {}
|
|
shared_ptr(int* counter) : counter(counter) {}
|
|
|
shared_ptr(const shared_ptr& other) : counter(other.counter) {
|
|
shared_ptr(const shared_ptr& other) : counter(other.counter) {
|
|
|
- if(!is_tagged()) _inc_counter();
|
|
|
|
|
|
|
+ _inc_counter();
|
|
|
}
|
|
}
|
|
|
shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) {
|
|
shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) {
|
|
|
other.counter = nullptr;
|
|
other.counter = nullptr;
|
|
|
}
|
|
}
|
|
|
- ~shared_ptr() { if(!is_tagged()) _dec_counter(); }
|
|
|
|
|
|
|
+ ~shared_ptr() { _dec_counter(); }
|
|
|
|
|
|
|
|
bool operator==(const shared_ptr& other) const { return counter == other.counter; }
|
|
bool operator==(const shared_ptr& other) const { return counter == other.counter; }
|
|
|
bool operator!=(const shared_ptr& other) const { return counter != other.counter; }
|
|
bool operator!=(const shared_ptr& other) const { return counter != other.counter; }
|
|
@@ -48,10 +66,6 @@ namespace pkpy{
|
|
|
bool operator!=(std::nullptr_t) const { return counter != nullptr; }
|
|
bool operator!=(std::nullptr_t) const { return counter != nullptr; }
|
|
|
|
|
|
|
|
shared_ptr& operator=(const shared_ptr& other) {
|
|
shared_ptr& operator=(const shared_ptr& other) {
|
|
|
- if(is_tagged()) {
|
|
|
|
|
- counter = other.counter;
|
|
|
|
|
- return *this;
|
|
|
|
|
- }
|
|
|
|
|
_dec_counter();
|
|
_dec_counter();
|
|
|
counter = other.counter;
|
|
counter = other.counter;
|
|
|
_inc_counter();
|
|
_inc_counter();
|
|
@@ -59,11 +73,6 @@ namespace pkpy{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
shared_ptr& operator=(shared_ptr&& other) noexcept {
|
|
shared_ptr& operator=(shared_ptr&& other) noexcept {
|
|
|
- if(is_tagged()) {
|
|
|
|
|
- counter = other.counter;
|
|
|
|
|
- other.counter = nullptr;
|
|
|
|
|
- return *this;
|
|
|
|
|
- }
|
|
|
|
|
_dec_counter();
|
|
_dec_counter();
|
|
|
counter = other.counter;
|
|
counter = other.counter;
|
|
|
other.counter = nullptr;
|
|
other.counter = nullptr;
|
|
@@ -80,24 +89,28 @@ namespace pkpy{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void reset(){
|
|
void reset(){
|
|
|
- if(!is_tagged()) _dec_counter();
|
|
|
|
|
|
|
+ _dec_counter();
|
|
|
counter = nullptr;
|
|
counter = nullptr;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template <typename __VAL>
|
|
template <typename __VAL>
|
|
|
- inline __VAL cast() const { return reinterpret_cast<__VAL>(counter); }
|
|
|
|
|
|
|
+ inline __VAL cast() const {
|
|
|
|
|
+ static_assert(std::is_same_v<T, PyObject>, "T must be PyObject");
|
|
|
|
|
+ return reinterpret_cast<__VAL>(counter);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- inline bool is_tagged() const { return (cast<std::uintptr_t>() & 0b11) != 0b00; }
|
|
|
|
|
- inline bool is_tag_00() const { return (cast<std::uintptr_t>() & 0b11) == 0b00; }
|
|
|
|
|
- inline bool is_tag_01() const { return (cast<std::uintptr_t>() & 0b11) == 0b01; }
|
|
|
|
|
- inline bool is_tag_10() const { return (cast<std::uintptr_t>() & 0b11) == 0b10; }
|
|
|
|
|
- inline bool is_tag_11() const { return (cast<std::uintptr_t>() & 0b11) == 0b11; }
|
|
|
|
|
|
|
+ inline bool is_tagged() const { return (cast<i64>() & 0b11) != 0b00; }
|
|
|
|
|
+ inline bool is_tag_00() const { return (cast<i64>() & 0b11) == 0b00; }
|
|
|
|
|
+ inline bool is_tag_01() const { return (cast<i64>() & 0b11) == 0b01; }
|
|
|
|
|
+ inline bool is_tag_10() const { return (cast<i64>() & 0b11) == 0b10; }
|
|
|
|
|
+ inline bool is_tag_11() const { return (cast<i64>() & 0b11) == 0b11; }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename U, typename... Args>
|
|
template <typename T, typename U, typename... Args>
|
|
|
shared_ptr<T> make_shared(Args&&... args) {
|
|
shared_ptr<T> make_shared(Args&&... args) {
|
|
|
static_assert(std::is_base_of_v<T, U>, "U must be derived from T");
|
|
static_assert(std::is_base_of_v<T, U>, "U must be derived from T");
|
|
|
static_assert(std::has_virtual_destructor_v<T>, "T must have virtual destructor");
|
|
static_assert(std::has_virtual_destructor_v<T>, "T must have virtual destructor");
|
|
|
|
|
+ static_assert(!std::is_same_v<T, PyObject> || (!std::is_same_v<U, i64> && !std::is_same_v<U, f64>));
|
|
|
int* p = SpAllocator<T>::template alloc<U>(); *p = 1;
|
|
int* p = SpAllocator<T>::template alloc<U>(); *p = 1;
|
|
|
new(p+1) U(std::forward<Args>(args)...);
|
|
new(p+1) U(std::forward<Args>(args)...);
|
|
|
return shared_ptr<T>(p);
|
|
return shared_ptr<T>(p);
|
|
@@ -109,4 +122,7 @@ namespace pkpy{
|
|
|
new(p+1) T(std::forward<Args>(args)...);
|
|
new(p+1) T(std::forward<Args>(args)...);
|
|
|
return shared_ptr<T>(p);
|
|
return shared_ptr<T>(p);
|
|
|
}
|
|
}
|
|
|
-};
|
|
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static_assert(sizeof(i64) == sizeof(pkpy::shared_ptr<PyObject>));
|
|
|
|
|
+static_assert(sizeof(f64) == sizeof(pkpy::shared_ptr<PyObject>));
|