1 // 2 // detail/object_pool.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_DETAIL_OBJECT_POOL_HPP 12 #define BOOST_ASIO_DETAIL_OBJECT_POOL_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/noncopyable.hpp> 19 20 #include <boost/asio/detail/push_options.hpp> 21 22 namespace boost { 23 namespace asio { 24 namespace detail { 25 26 template <typename Object> 27 class object_pool; 28 29 class object_pool_access 30 { 31 public: 32 template <typename Object> create()33 static Object* create() 34 { 35 return new Object; 36 } 37 38 template <typename Object, typename Arg> create(Arg arg)39 static Object* create(Arg arg) 40 { 41 return new Object(arg); 42 } 43 44 template <typename Object> destroy(Object * o)45 static void destroy(Object* o) 46 { 47 delete o; 48 } 49 50 template <typename Object> next(Object * o)51 static Object*& next(Object* o) 52 { 53 return o->next_; 54 } 55 56 template <typename Object> prev(Object * o)57 static Object*& prev(Object* o) 58 { 59 return o->prev_; 60 } 61 }; 62 63 template <typename Object> 64 class object_pool 65 : private noncopyable 66 { 67 public: 68 // Constructor. object_pool()69 object_pool() 70 : live_list_(0), 71 free_list_(0) 72 { 73 } 74 75 // Destructor destroys all objects. ~object_pool()76 ~object_pool() 77 { 78 destroy_list(live_list_); 79 destroy_list(free_list_); 80 } 81 82 // Get the object at the start of the live list. first()83 Object* first() 84 { 85 return live_list_; 86 } 87 88 // Allocate a new object. alloc()89 Object* alloc() 90 { 91 Object* o = free_list_; 92 if (o) 93 free_list_ = object_pool_access::next(free_list_); 94 else 95 o = object_pool_access::create<Object>(); 96 97 object_pool_access::next(o) = live_list_; 98 object_pool_access::prev(o) = 0; 99 if (live_list_) 100 object_pool_access::prev(live_list_) = o; 101 live_list_ = o; 102 103 return o; 104 } 105 106 // Allocate a new object with an argument. 107 template <typename Arg> alloc(Arg arg)108 Object* alloc(Arg arg) 109 { 110 Object* o = free_list_; 111 if (o) 112 free_list_ = object_pool_access::next(free_list_); 113 else 114 o = object_pool_access::create<Object>(arg); 115 116 object_pool_access::next(o) = live_list_; 117 object_pool_access::prev(o) = 0; 118 if (live_list_) 119 object_pool_access::prev(live_list_) = o; 120 live_list_ = o; 121 122 return o; 123 } 124 125 // Free an object. Moves it to the free list. No destructors are run. free(Object * o)126 void free(Object* o) 127 { 128 if (live_list_ == o) 129 live_list_ = object_pool_access::next(o); 130 131 if (object_pool_access::prev(o)) 132 { 133 object_pool_access::next(object_pool_access::prev(o)) 134 = object_pool_access::next(o); 135 } 136 137 if (object_pool_access::next(o)) 138 { 139 object_pool_access::prev(object_pool_access::next(o)) 140 = object_pool_access::prev(o); 141 } 142 143 object_pool_access::next(o) = free_list_; 144 object_pool_access::prev(o) = 0; 145 free_list_ = o; 146 } 147 148 private: 149 // Helper function to destroy all elements in a list. destroy_list(Object * list)150 void destroy_list(Object* list) 151 { 152 while (list) 153 { 154 Object* o = list; 155 list = object_pool_access::next(o); 156 object_pool_access::destroy(o); 157 } 158 } 159 160 // The list of live objects. 161 Object* live_list_; 162 163 // The free list. 164 Object* free_list_; 165 }; 166 167 } // namespace detail 168 } // namespace asio 169 } // namespace boost 170 171 #include <boost/asio/detail/pop_options.hpp> 172 173 #endif // BOOST_ASIO_DETAIL_OBJECT_POOL_HPP 174