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.

137 lines
2.5 KiB

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. 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. 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. unique_ptr(unique_ptr&) = delete;
  34. unique_ptr(unique_ptr&& oth)
  35. : data(oth.data)
  36. , owner(oth.owner)
  37. {
  38. oth.data = nullptr;
  39. }
  40. unique_ptr& operator=(unique_ptr&) = delete;
  41. unique_ptr& operator=(unique_ptr&& oth) {
  42. dirty_clear();
  43. data = oth.data;
  44. owner = oth.owner;
  45. }
  46. ~unique_ptr() {
  47. dirty_clear();
  48. }
  49. };
  50. template<typename T>
  51. class shared_ptr {
  52. T* data;
  53. std::atomic_int* refcounter;
  54. gp::allocator& owner;
  55. shared_ptr(T* _data, gp::allocator& _owner)
  56. : data(data)
  57. , owner(_owner)
  58. {}
  59. void dirty_clear() {
  60. if(!refcounter) return;
  61. if(refcounter->fetch_sub(1, std::memory_order::acq_rel) == 0) {
  62. if(data) {
  63. data->~T();
  64. owner.deallocate(refcounter);
  65. owner.deallocate(data);
  66. }
  67. }
  68. }
  69. public:
  70. template<typename ...U>
  71. shared_ptr make(gp::allocator& owner, U&&... args) {
  72. auto ptr = owner.allocate(sizeof(T));
  73. auto shared_atomic = owner.allocate(sizeof(std::atomic_int));
  74. refcounter = new(shared_atomic) std::atomic_int();
  75. refcounter->store(1);
  76. return shared_ptr(new(ptr) T(gp::forward<U>(args)...), owner);
  77. }
  78. T& operator->() {
  79. return *data;
  80. }
  81. T& operator*() {
  82. return *data;
  83. }
  84. shared_ptr(shared_ptr& oth) {
  85. oth.refcounter->fetch_add(1, std::memory_order::acquire);
  86. data = oth.data;
  87. refcounter = oth.refcounter;
  88. owner = oth.owner;
  89. }
  90. shared_ptr(shared_ptr&& oth)
  91. : data(oth.data)
  92. , owner(oth.owner)
  93. {
  94. oth.data = nullptr;
  95. oth.refcounter = nullptr;
  96. }
  97. shared_ptr& operator=(shared_ptr& oth) {
  98. dirty_clear();
  99. (*oth.refcounter)++;
  100. data = oth.data;
  101. refcounter = oth.refcounter;
  102. owner = oth.owner;
  103. }
  104. shared_ptr& operator=(shared_ptr&& oth) {
  105. dirty_clear();
  106. data = oth.data;
  107. owner = oth.owner;
  108. }
  109. ~shared_ptr() {
  110. dirty_clear();
  111. }
  112. };
  113. }