| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #ifndef DATASTAX_INTERNAL_FIXED_ALLOCATOR_HPP |
| #define DATASTAX_INTERNAL_FIXED_ALLOCATOR_HPP |
| |
| #include "aligned_storage.hpp" |
| #include "macros.hpp" |
| #include "memory.hpp" |
| |
| #include <limits> |
| #include <memory> |
| |
| namespace datastax { namespace internal { |
| |
| // This is an allocator that starts using a fixed size buffer that only |
| // uses the heap when exceeded. The allocator can be |
| // copied so the vector itself needs to hold on to the fixed buffer. |
| |
| template <class T, size_t N> |
| class FixedAllocator { |
| public: |
| typedef size_t size_type; |
| typedef ptrdiff_t difference_type; |
| typedef T value_type; |
| typedef T* pointer; |
| typedef const T* const_pointer; |
| typedef T& reference; |
| typedef const T& const_reference; |
| |
| template <class U> |
| struct rebind { |
| typedef FixedAllocator<U, N> other; |
| }; |
| |
| struct Fixed { |
| Fixed() |
| : is_used(false) {} |
| |
| // See aligned_storage.hpp for why this is required |
| typedef AlignedStorage<N * sizeof(T), ALIGN_OF(T)> Storage; |
| |
| bool is_used; |
| Storage data; |
| }; |
| |
| FixedAllocator() |
| : fixed_(NULL) {} |
| |
| FixedAllocator(Fixed* fixed) |
| : fixed_(fixed) {} |
| |
| FixedAllocator(const FixedAllocator<T, N>& allocator) |
| : fixed_(allocator.fixed_) {} |
| |
| template <class U, size_t M> |
| FixedAllocator(const FixedAllocator<U, M>& allocator) |
| : fixed_(NULL) {} |
| |
| FixedAllocator(const std::allocator<T>& allocator) |
| : fixed_(NULL) {} |
| |
| pointer address(reference x) const { return &x; } |
| |
| const_pointer address(const_reference x) const { return &x; } |
| |
| pointer allocate(size_type n, const_pointer hint = NULL) { |
| if (fixed_ != NULL && !fixed_->is_used && n <= N) { |
| fixed_->is_used = true; // Don't reuse the buffer |
| return static_cast<T*>(fixed_->data.address()); |
| } else { |
| return static_cast<T*>(Memory::malloc(sizeof(T) * n)); |
| } |
| } |
| |
| void deallocate(pointer p, size_type n) { |
| if (fixed_ != NULL && fixed_->data.address() == p) { |
| fixed_->is_used = false; // It's safe to reuse the buffer |
| } else { |
| Memory::free(p); |
| } |
| } |
| |
| void construct(pointer p, const_reference x) { new (p) value_type(x); } |
| |
| void destroy(pointer p) { p->~value_type(); } |
| |
| size_type max_size() const throw() { return std::numeric_limits<size_type>::max(); } |
| |
| private: |
| Fixed* fixed_; |
| }; |
| |
| }} // namespace datastax::internal |
| |
| #endif |