memory.h 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #pragma once
  2. #include "common.h"
  3. namespace pkpy{
  4. template<typename T>
  5. struct SpAllocator {
  6. template<typename U>
  7. inline static int* alloc(){
  8. return (int*)malloc(sizeof(int) + sizeof(U));
  9. }
  10. inline static void dealloc(int* counter){
  11. ((T*)(counter + 1))->~T();
  12. free(counter);
  13. }
  14. };
  15. template <typename T>
  16. class shared_ptr {
  17. int* counter = nullptr;
  18. #define _t() ((T*)(counter + 1))
  19. #define _inc_counter() if(counter) ++(*counter)
  20. #define _dec_counter() if(counter && --(*counter) == 0){ SpAllocator<T>::dealloc(counter); }
  21. public:
  22. shared_ptr() {}
  23. shared_ptr(int* counter) : counter(counter) {}
  24. shared_ptr(const shared_ptr& other) : counter(other.counter) {
  25. _inc_counter();
  26. }
  27. shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) {
  28. other.counter = nullptr;
  29. }
  30. ~shared_ptr() { _dec_counter(); }
  31. bool operator==(const shared_ptr& other) const {
  32. return counter == other.counter;
  33. }
  34. bool operator!=(const shared_ptr& other) const {
  35. return counter != other.counter;
  36. }
  37. bool operator==(std::nullptr_t) const {
  38. return counter == nullptr;
  39. }
  40. bool operator!=(std::nullptr_t) const {
  41. return counter != nullptr;
  42. }
  43. shared_ptr& operator=(const shared_ptr& other) {
  44. _dec_counter();
  45. counter = other.counter;
  46. _inc_counter();
  47. return *this;
  48. }
  49. shared_ptr& operator=(shared_ptr&& other) noexcept {
  50. _dec_counter();
  51. counter = other.counter;
  52. other.counter = nullptr;
  53. return *this;
  54. }
  55. T& operator*() const { return *_t(); }
  56. T* operator->() const { return _t(); }
  57. T* get() const { return _t(); }
  58. int use_count() const { return counter ? *counter : 0; }
  59. void reset(){
  60. _dec_counter();
  61. counter = nullptr;
  62. }
  63. };
  64. #undef _t
  65. #undef _inc_counter
  66. #undef _dec_counter
  67. template <typename T, typename U, typename... Args>
  68. shared_ptr<T> make_shared(Args&&... args) {
  69. static_assert(std::is_base_of_v<T, U>, "U must be derived from T");
  70. static_assert(std::has_virtual_destructor_v<T>, "T must have virtual destructor");
  71. int* p = SpAllocator<T>::template alloc<U>(); *p = 1;
  72. new(p+1) U(std::forward<Args>(args)...);
  73. return shared_ptr<T>(p);
  74. }
  75. template <typename T, typename... Args>
  76. shared_ptr<T> make_shared(Args&&... args) {
  77. int* p = SpAllocator<T>::template alloc<T>(); *p = 1;
  78. new(p+1) T(std::forward<Args>(args)...);
  79. return shared_ptr<T>(p);
  80. }
  81. };