General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
2.4 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #pragma once
  2. #include "gp/algorithm/modifiers.hpp"
  3. #include "gp/algorithm/move.hpp"
  4. #include "gp/buffer.hpp"
  5. #include "gp/function.hpp"
  6. template<typename T>
  7. class unique_ptr {
  8. T* data;
  9. gp::allocator const& owner;
  10. unique_ptr(T* _data, gp::allocator const& _owner)
  11. : data(data)
  12. , owner(_owner)
  13. {}
  14. void dirty_clear() {
  15. if(data) {
  16. data->~T();
  17. owner.deallocate(data);
  18. }
  19. }
  20. public:
  21. template<typename ...U>
  22. unique_ptr make(gp::allocator& owner, U&&... args) {
  23. auto ptr = owner.allocate(sizeof(T));
  24. return unique_ptr(new(ptr) T(gp::forward<U>(args)...), owner);
  25. }
  26. T& operator->() {
  27. return *data;
  28. }
  29. T& operator*() {
  30. return *data;
  31. }
  32. unique_ptr(unique_ptr&) = delete;
  33. unique_ptr(unique_ptr&& oth)
  34. : data(oth.data)
  35. , owner(oth.owner)
  36. {
  37. oth.data = nullptr;
  38. }
  39. unique_ptr& operator=(unique_ptr&) = delete;
  40. unique_ptr& operator=(unique_ptr&& oth) {
  41. dirty_clear();
  42. data = oth.data;
  43. owner = oth.owner;
  44. }
  45. ~unique_ptr() {
  46. dirty_clear();
  47. }
  48. };
  49. template<typename T>
  50. class shared_ptr {
  51. T* data;
  52. std::atomic_int* refcounter;
  53. gp::allocator const& owner;
  54. shared_ptr(T* _data, gp::allocator const& _owner)
  55. : data(data)
  56. , owner(_owner)
  57. {}
  58. void dirty_clear() {
  59. if(!refcounter) return;
  60. if(refcounter->fetch_sub(1, std::memory_order::acq_rel) == 0) {
  61. if(data) {
  62. data->~T();
  63. owner.deallocate(refcounter);
  64. owner.deallocate(data);
  65. }
  66. }
  67. }
  68. public:
  69. template<typename ...U>
  70. shared_ptr make(gp::allocator& owner, U&&... args) {
  71. auto ptr = owner.allocate(sizeof(T));
  72. auto shared_atomic = owner.allocate(sizeof(std::atomic_int));
  73. refcounter = new(shared_atomic) std::atomic_int();
  74. refcounter->store(1);
  75. return shared_ptr(new(ptr) T(gp::forward<U>(args)...), owner);
  76. }
  77. T& operator->() {
  78. return *data;
  79. }
  80. T& operator*() {
  81. return *data;
  82. }
  83. shared_ptr(shared_ptr& oth) {
  84. oth.refcounter->fetch_add(1, std::memory_order::acquire);
  85. data = oth.data;
  86. refcounter = oth.refcounter;
  87. owner = oth.owner;
  88. }
  89. shared_ptr(shared_ptr&& oth)
  90. : data(oth.data)
  91. , owner(oth.owner)
  92. {
  93. oth.data = nullptr;
  94. oth.refcounter = nullptr;
  95. }
  96. shared_ptr& operator=(shared_ptr& oth) {
  97. dirty_clear();
  98. (*oth.refcounter)++;
  99. data = oth.data;
  100. refcounter = oth.refcounter;
  101. owner = oth.owner;
  102. }
  103. shared_ptr& operator=(shared_ptr&& oth) {
  104. dirty_clear();
  105. data = oth.data;
  106. owner = oth.owner;
  107. }
  108. ~shared_ptr() {
  109. dirty_clear();
  110. }
  111. };