5 #include <libcopp/utils/config/libcopp_build_features.h>
25 LIBCOPP_COPP_NAMESPACE_BEGIN
26 template <
typename TAlloc>
30 using ptr_type = std::shared_ptr<stack_pool<TAlloc> >;
64 memset(&limits_, 0,
sizeof(limits_));
65 memset(&conf_, 0,
sizeof(conf_));
66 conf_.stack_size = LIBCOPP_COPP_NAMESPACE_ID::stack_traits::default_size();
78 if (sz <= LIBCOPP_COPP_NAMESPACE_ID::stack_traits::minimum_size()) {
79 sz = LIBCOPP_COPP_NAMESPACE_ID::stack_traits::minimum_size();
81 sz = LIBCOPP_COPP_NAMESPACE_ID::stack_traits::round_to_page_size(sz);
84 if (sz != conf_.stack_size) {
88 return conf_.stack_size = sz;
103 inline void set_auto_gc(
bool v) LIBCOPP_MACRO_NOEXCEPT { conf_.auto_gc = v; }
118 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
119 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard(
123 if (0 != conf_.max_stack_number && limits_.used_stack_number >= conf_.max_stack_number) {
129 if (0 != conf_.max_stack_size && limits_.used_stack_size + conf_.stack_size > conf_.max_stack_size) {
136 if (!free_list_.empty()) {
137 typename std::list<stack_context>::reverse_iterator iter = free_list_.rbegin();
138 assert(iter != free_list_.rend());
142 --limits_.free_stack_number;
144 limits_.free_stack_number = free_list_.size() - 1;
148 limits_.free_stack_size -= (*iter).size;
150 limits_.free_stack_size = 0;
156 free_list_.pop_back();
159 ++limits_.used_stack_number;
160 limits_.used_stack_size += ctx.size;
164 free_list_.pop_back();
169 alloc_.allocate(ctx, conf_.stack_size);
170 if (
nullptr != ctx.sp && ctx.size > 0) {
172 ++limits_.used_stack_number;
173 limits_.used_stack_size += ctx.size;
175 conf_.stack_offset = ctx.size - conf_.stack_size;
184 assert(ctx.sp && ctx.size > 0);
186 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
187 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard(
191 if (ctx.sp ==
nullptr || 0 == ctx.size) {
197 limits_.used_stack_size -= ctx.size;
199 limits_.used_stack_size = 0;
203 --limits_.used_stack_number;
207 if (ctx.size != conf_.stack_size + conf_.stack_offset) {
208 alloc_.deallocate(ctx);
213 free_list_.push_back(ctx);
216 ++limits_.free_stack_number;
217 limits_.free_stack_size += ctx.size;
229 if (limits_.used_stack_size >= limits_.free_stack_size && limits_.used_stack_number >= limits_.free_stack_number) {
234 if (0 != conf_.min_stack_size || 0 != conf_.min_stack_number) {
235 bool min_stack_size =
236 conf_.min_stack_size == 0 || limits_.used_stack_size + limits_.free_stack_size <= conf_.min_stack_size;
237 bool min_stack_number = conf_.min_stack_number == 0 ||
238 limits_.free_stack_number + limits_.used_stack_number <= conf_.min_stack_number;
239 if (min_stack_size && min_stack_number) {
244 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
245 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard(
249 size_t keep_size = limits_.free_stack_size >> 1;
250 size_t keep_number = limits_.free_stack_number >> 1;
251 size_t left_gc = conf_.gc_number;
252 while (limits_.free_stack_size > keep_size || limits_.free_stack_number > keep_number) {
253 if (free_list_.empty()) {
254 limits_.free_stack_size = 0;
255 limits_.free_stack_number = 0;
259 typename std::list<stack_context>::iterator iter = free_list_.begin();
260 assert(iter != free_list_.end());
263 --limits_.free_stack_number;
265 limits_.free_stack_number = free_list_.size() - 1;
269 limits_.free_stack_size -= (*iter).size;
271 limits_.free_stack_size = 0;
274 alloc_.deallocate(*iter);
275 free_list_.pop_front();
293 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
294 LIBCOPP_COPP_NAMESPACE_ID::util::lock::lock_holder<LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock> lock_guard(
298 limits_.free_stack_size = 0;
299 limits_.free_stack_number = 0;
301 for (
typename std::list<stack_context>::iterator iter = free_list_.begin(); iter != free_list_.end(); ++iter) {
302 alloc_.deallocate(*iter);
312 #if !defined(LIBCOPP_DISABLE_ATOMIC_LOCK) || !(LIBCOPP_DISABLE_ATOMIC_LOCK)
317 LIBCOPP_COPP_NAMESPACE_END
#define LIBCOPP_UTIL_LOCK_ATOMIC_THREAD_FENCE(x)
size_t get_stack_size_offset() const
size_t get_min_stack_number() const LIBCOPP_MACRO_NOEXCEPT
void set_gc_once_number(size_t v) LIBCOPP_MACRO_NOEXCEPT
std::shared_ptr< stack_pool< TAlloc > > ptr_type
void set_min_stack_size(size_t sz) LIBCOPP_MACRO_NOEXCEPT
allocator_type allocator_t
const allocator_type & get_origin_allocator() const LIBCOPP_MACRO_NOEXCEPT
size_t get_stack_size() const
void set_min_stack_number(size_t sz) LIBCOPP_MACRO_NOEXCEPT
void set_auto_gc(bool v) LIBCOPP_MACRO_NOEXCEPT
size_t get_max_stack_size() const LIBCOPP_MACRO_NOEXCEPT
size_t get_gc_once_number() const LIBCOPP_MACRO_NOEXCEPT
size_t get_max_stack_number() const LIBCOPP_MACRO_NOEXCEPT
size_t set_stack_size(size_t sz)
bool is_auto_gc() const LIBCOPP_MACRO_NOEXCEPT
allocator_type & get_origin_allocator() LIBCOPP_MACRO_NOEXCEPT
stack_pool(constructor_delegator)
std::list< stack_context > free_list_
void allocate(stack_context &ctx) LIBCOPP_MACRO_NOEXCEPT
void set_max_stack_number(size_t sz) LIBCOPP_MACRO_NOEXCEPT
stack_pool(const stack_pool &)=delete
const limit_t & get_limit() const
LIBCOPP_COPP_NAMESPACE_ID::util::lock::spin_lock action_lock_
size_t get_min_stack_size() const LIBCOPP_MACRO_NOEXCEPT
void set_max_stack_size(size_t sz) LIBCOPP_MACRO_NOEXCEPT
void deallocate(stack_context &ctx) LIBCOPP_MACRO_NOEXCEPT
#define COPP_LIKELY_IF(...)
锁管理器 Licensed under the MIT licenses.
自旋锁 Licensed under the MIT licenses.