1 /*
2 ** Copyright 2018 Bloomberg Finance L.P.
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 #ifndef BLOOMBERG_QUANTUM_POOL_MANAGER_H
17 #define BLOOMBERG_QUANTUM_POOL_MANAGER_H
18
19
20 #include <quantum/quantum_spinlock.h>
21 #include <memory>
22 #include <cassert>
23 #include <limits>
24 #include <type_traits>
25 #include <utility>
26
27 namespace Bloomberg {
28 namespace quantum {
29
30 //==============================================================================
31 // struct ContiguousPoolManager
32 //==============================================================================
33 /// @struct ContiguousPoolManager.
34 /// @brief Provides fast (quasi zero-time) in-place allocation for STL containers.
35 /// Objects are allocated from a contiguous buffer (aka object pool). When the
36 /// buffer is exhausted, allocation is delegated to the heap. The default
37 /// buffer size is 1000.
38 /// @tparam T The type to allocate.
39 /// @note This allocator is thread safe. For internal use only.
40 template <typename T>
41 struct ContiguousPoolManager
42 {
43 template <typename U>
44 friend struct ContiguousPoolManager;
45 //------------------------------ Typedefs ----------------------------------
46 typedef ContiguousPoolManager<T> this_type;
47 typedef T value_type;
48 typedef value_type* pointer;
49 typedef const value_type* const_pointer;
50 typedef value_type& reference;
51 typedef const value_type& const_reference;
52 typedef size_t size_type;
53 typedef uint16_t index_type;
54 typedef std::ptrdiff_t difference_type;
55 typedef std::true_type propagate_on_container_move_assignment;
56 typedef std::true_type propagate_on_container_copy_assignment;
57 typedef std::true_type propagate_on_container_swap;
58 typedef std::false_type is_always_equal;
59 typedef std::false_type default_constructor;
60 typedef std::aligned_storage<sizeof(T), alignof(T)> storage_type;
61 typedef typename storage_type::type aligned_type;
62
63 //------------------------------- Methods ----------------------------------
64 ContiguousPoolManager();
65 ContiguousPoolManager(aligned_type* buffer, index_type size);
66
67 template <typename U>
68 struct rebind
69 {
70 typedef ContiguousPoolManager<U> other;
71 };
72 //Rebound types
73 template <typename U>
74 ContiguousPoolManager(const ContiguousPoolManager<U>& other);
75 template <typename U>
76 ContiguousPoolManager(ContiguousPoolManager<U>&& other);
77 template <typename U>
78 ContiguousPoolManager& operator=(const ContiguousPoolManager<U>&) = delete;
79 template <typename U>
80 ContiguousPoolManager& operator=(ContiguousPoolManager<U>&&) = delete;
81
82 static ContiguousPoolManager
select_on_container_copy_constructionContiguousPoolManager83 select_on_container_copy_construction(const ContiguousPoolManager& other) {
84 return ContiguousPoolManager(other);
85 }
86 bool operator==(const this_type& other) const {
87 return _control && other._control && (_control->_buffer == other._control->_buffer);
88 }
89 bool operator!=(const this_type& other) const {
90 return !operator==(other);
91 }
92
93 //------------------------- Accessors ------------------------------
94 void setBuffer(aligned_type* buffer, index_type size);
95 pointer address(reference x) const;
96 const_pointer address(const_reference x) const;
97 size_type max_size() const;
98 template <typename... Args >
99 void construct(T* p, Args&&... args);
100 void destroy(pointer p);
101 pointer allocate(size_type = 1, const_pointer = 0);
102 void deallocate(pointer p, size_type = 1);
103 template <typename... Args >
104 pointer create(Args&&... args);
105 void dispose(pointer p);
106 size_t allocatedBlocks() const;
107 size_t allocatedHeapBlocks() const;
108 bool isFull() const;
109 bool isEmpty() const;
110 index_type size() const;
111 explicit operator bool() const;
112
113 private:
114 pointer bufferStart();
115 pointer bufferEnd();
116 bool isManaged(pointer p);
117 index_type blockIndex(pointer p);
118 bool findContiguous(index_type n);
119
120 //------------------------------- Members ----------------------------------
121 struct Control {
~ControlContiguousPoolManager::Control122 ~Control() {
123 delete[] _freeBlocks;
124 }
125 index_type _size{0};
126 aligned_type* _buffer{nullptr}; //non-owning
127 index_type* _freeBlocks{nullptr};
128 ssize_t _freeBlockIndex{-1};
129 size_t _numHeapAllocatedBlocks{0};
130 mutable SpinLock _spinlock;
131 };
132 std::shared_ptr<Control> _control;
133 };
134
135 template <typename U, typename T>
resize(size_t t_size)136 size_t resize(size_t t_size)
137 {
138 return (t_size*sizeof(U))/sizeof(T);
139 }
140
141 }} //namespaces
142
143 #include <quantum/impl/quantum_contiguous_pool_manager_impl.h>
144
145 #endif //BLOOMBERG_QUANTUM_POOL_MANAGER_H
146
147