// // detail/thread_info_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef ASIO_DETAIL_THREAD_INFO_BASE_HPP #define ASIO_DETAIL_THREAD_INFO_BASE_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include "asio/detail/noncopyable.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace detail { class thread_info_base : private noncopyable { public: struct default_tag { enum { mem_index = 0 }; }; struct awaitable_frame_tag { enum { mem_index = 1 }; }; struct executor_function_tag { enum { mem_index = 2 }; }; thread_info_base() { for (int i = 0; i < max_mem_index; ++i) reusable_memory_[i] = 0; } ~thread_info_base() { for (int i = 0; i < max_mem_index; ++i) if (reusable_memory_[i]) ::operator delete(reusable_memory_[i]); } static void* allocate(thread_info_base* this_thread, std::size_t size) { return allocate(default_tag(), this_thread, size); } static void deallocate(thread_info_base* this_thread, void* pointer, std::size_t size) { deallocate(default_tag(), this_thread, pointer, size); } template static void* allocate(Purpose, thread_info_base* this_thread, std::size_t size) { std::size_t chunks = (size + chunk_size - 1) / chunk_size; if (this_thread && this_thread->reusable_memory_[Purpose::mem_index]) { void* const pointer = this_thread->reusable_memory_[Purpose::mem_index]; this_thread->reusable_memory_[Purpose::mem_index] = 0; unsigned char* const mem = static_cast(pointer); if (static_cast(mem[0]) >= chunks) { mem[size] = mem[0]; return pointer; } ::operator delete(pointer); } void* const pointer = ::operator new(chunks * chunk_size + 1); unsigned char* const mem = static_cast(pointer); mem[size] = (chunks <= UCHAR_MAX) ? static_cast(chunks) : 0; return pointer; } template static void deallocate(Purpose, thread_info_base* this_thread, void* pointer, std::size_t size) { if (size <= chunk_size * UCHAR_MAX) { if (this_thread && this_thread->reusable_memory_[Purpose::mem_index] == 0) { unsigned char* const mem = static_cast(pointer); mem[0] = mem[size]; this_thread->reusable_memory_[Purpose::mem_index] = pointer; return; } } ::operator delete(pointer); } private: enum { chunk_size = 4 }; enum { max_mem_index = 3 }; void* reusable_memory_[max_mem_index]; }; } // namespace detail } // namespace asio #include "asio/detail/pop_options.hpp" #endif // ASIO_DETAIL_THREAD_INFO_BASE_HPP