TCPSPSuite
intrusive_shared_ptr.hpp
1 //
2 // Created by lukas on 18.05.18.
3 //
4 
5 #ifndef TCPSPSUITE_INTRUSIVE_SHARED_PTR_HPP
6 #define TCPSPSUITE_INTRUSIVE_SHARED_PTR_HPP
7 
8 #include <list>
9 
10 template <class T, class Accessor, bool safe_mode = false>
11 class IntrusiveSharedPtr {
12 public:
13  using own_type = IntrusiveSharedPtr<T, Accessor, safe_mode>;
14 
15  IntrusiveSharedPtr(const own_type & other) noexcept : content(other.content)
16  {
17  if (this->content != nullptr) {
18  Accessor::increment(this->content);
19  }
20  };
21 
22  IntrusiveSharedPtr(own_type && other) noexcept : content(other.content)
23  {
24  other.content = nullptr;
25  };
26 
27  IntrusiveSharedPtr(T * content_new) noexcept : content(content_new)
28  {
29  // TODO safety-assert
30  if (content_new != nullptr) {
31  Accessor::set_count(this->content, 1);
32  }
33  };
34 
35  IntrusiveSharedPtr() noexcept { this->content = nullptr; };
36 
37  ~IntrusiveSharedPtr()
38  {
39  if (this->content == nullptr)
40  return;
41 
42  // TODO safety-assert
43  Accessor::decrement(this->content);
44  if (Accessor::get_count(this->content) == 0) {
45  Accessor::deallocate(this->content);
46  }
47  };
48 
49  void
50  reset(T * content_new) noexcept
51  {
52  if (this->content != nullptr) {
53  // TODO safety-assert
54  Accessor::decrement(this->content);
55  if (Accessor::get_count(this->content) == 0) {
56  Accessor::deallocate(this->content);
57  }
58  }
59 
60  this->content = content_new;
61  // TODO safety-assert
62  if (this->content != nullptr) {
63  Accessor::set_count(content_new, 1);
64  }
65  };
66 
67  T & operator*() const noexcept { return *(this->content); };
68  T * operator->() const noexcept { return this->content; };
69 
70  T *
71  get() const noexcept
72  {
73  return this->content;
74  };
75 
76  own_type &
77  operator=(const own_type & other)
78  {
79  this->content = other.content;
80  if (this->content != nullptr) {
81  Accessor::increment(this->content);
82  }
83 
84  return *this;
85  }
86 
87  own_type &
88  operator=(own_type && other)
89  {
90  this->content = other.content;
91  other.content = nullptr;
92 
93  return *this;
94  }
95 
96 private:
97  T * content;
98 };
99 
100 template <class T>
101 class SharedPtrPool {
102 private:
103  class ContainerAccessor;
104 
105 public:
106  using PointerT = IntrusiveSharedPtr<T, ContainerAccessor>;
107 
108  class Container : public T {
109  public:
110  Container(SharedPtrPool<T> * pool_new) : T(), pool(pool_new), count(0) {}
111  Container() = delete;
112 
113  private:
114  SharedPtrPool<T> * pool;
115  size_t count;
116 
117  friend class ContainerAccessor;
118  friend class SharedPtrPool<T>;
119  };
120 
121  IntrusiveSharedPtr<T, ContainerAccessor>
122  get() noexcept
123  {
124  if (this->free.empty()) {
125  this->store.push_back(
126  std::vector<Container>(this->chunk_size, Container(this)));
127  for (Container & c : this->store.back()) {
128  this->free.push_back(&c);
129  }
130  }
131 
132  Container * c = this->free.back();
133  this->free.pop_back();
134  return IntrusiveSharedPtr<T, ContainerAccessor>((T *)c);
135  }
136 
137  SharedPtrPool() : chunk_size(10000) {}
138  SharedPtrPool(size_t chunk_size_new) : chunk_size(chunk_size_new) {}
139 
140 private:
141  class ContainerAccessor {
142  public:
143  static size_t
144  get_count(const T * c) noexcept
145  {
146  return ((const Container *)c)->Container::count;
147  }
148  static void
149  set_count(T * c, size_t count) noexcept
150  {
151  ((Container *)c)->Container::count = count;
152  }
153  static void
154  increment(T * c) noexcept
155  {
156  ((Container *)c)->Container::count++;
157  }
158  static void
159  decrement(T * c) noexcept
160  {
161  ((Container *)c)->Container::count--;
162  }
163  static void
164  deallocate(T * c) noexcept
165  {
166  ((Container *)c)->Container::pool->free.push_back((Container *)c);
167  // TODO safety-assert?
168  }
169  };
170 
171  std::list<std::vector<Container>> store;
172  std::vector<Container *> free;
173 
174  size_t chunk_size;
175 };
176 
177 #endif // TCPSPSUITE_INTRUSIVE_SHARED_PTR_HPP