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