General Purpose library for Freestanding C++ and POSIX systems
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

145 linhas
2.6 KiB

3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
3 anos atrás
  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. 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. , owner(_owner)
  61. {}
  62. void dirty_clear() {
  63. if(!refcounter) return;
  64. if(refcounter->fetch_sub(1, std::memory_order::acq_rel) == 0) {
  65. if(data) {
  66. data->~T();
  67. owner.deallocate(refcounter);
  68. owner.deallocate(data);
  69. }
  70. }
  71. }
  72. public:
  73. template<typename ...U>
  74. static shared_ptr make(gp::allocator& owner, U&&... args) {
  75. auto ptr = owner.allocate(sizeof(T));
  76. auto shared_atomic = owner.allocate(sizeof(std::atomic_int));
  77. refcounter = new(shared_atomic) std::atomic_int();
  78. refcounter->store(1);
  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. }