#pragma once #include "common.h" #include namespace pkpy{ template struct shared_ptr { int* counter; T* _t() const noexcept { return (T*)(counter + 1); } void _inc_counter() { if(counter) ++(*counter); } void _dec_counter() { if(counter && --(*counter) == 0) {((T*)(counter + 1))->~T(); free(counter);} } public: shared_ptr() : counter(nullptr) {} shared_ptr(int* counter) : counter(counter) {} shared_ptr(const shared_ptr& other) : counter(other.counter) { _inc_counter(); } shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) { other.counter = nullptr; } ~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; } bool operator<=(const shared_ptr& other) const { return counter <= other.counter; } bool operator>=(const shared_ptr& other) const { return counter >= other.counter; } 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) { _dec_counter(); counter = other.counter; _inc_counter(); return *this; } shared_ptr& operator=(shared_ptr&& other) noexcept { _dec_counter(); counter = other.counter; other.counter = nullptr; return *this; } T& operator*() const { return *_t(); } T* operator->() const { return _t(); } T* get() const { return _t(); } int use_count() const { return counter ? *counter : 0; } void reset(){ _dec_counter(); counter = nullptr; } }; template shared_ptr make_sp(Args&&... args) { int* p = (int*)malloc(sizeof(int) + sizeof(T)); *p = 1; new(p+1) T(std::forward(args)...); return shared_ptr(p); } template struct FreeListA { std::vector buckets[__Bucket+1]; T* alloc(int n){ static_assert(std::is_standard_layout_v); T* p; if(n > __Bucket || buckets[n].empty()){ p = (T*)malloc(sizeof(T) * n); }else{ p = buckets[n].back(); buckets[n].pop_back(); } if constexpr(__ZeroInit){ // the constructor of T should be equivalent to zero initialization memset((void*)p, 0, sizeof(T) * n); } return p; } void dealloc(T* p, int n){ if(p == nullptr) return; if(n > __Bucket || buckets[n].size() >= 80){ free(p); }else{ buckets[n].push_back(p); } } ~FreeListA(){ for(int i=0; i<=__Bucket; i++){ for(T* p : buckets[i]) free(p); } } }; }; // namespace pkpy