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.

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