1  
//
1  
//
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/capy
7  
// Official repository: https://github.com/cppalliance/capy
8  
//
8  
//
9  

9  

10  
#include <boost/capy/ex/recycling_memory_resource.hpp>
10  
#include <boost/capy/ex/recycling_memory_resource.hpp>
11  

11  

12  
namespace boost {
12  
namespace boost {
13  
namespace capy {
13  
namespace capy {
14  

14  

15 -
recycling_memory_resource::pool&
15 +
recycling_memory_resource::~recycling_memory_resource() = default;
16 -
recycling_memory_resource::local() noexcept
 
17 -
{
 
18 -
    static thread_local pool p;
 
19 -
    return p;
 
20 -
}
 
21  

16  

22  
recycling_memory_resource::pool&
17  
recycling_memory_resource::pool&
23  
recycling_memory_resource::global() noexcept
18  
recycling_memory_resource::global() noexcept
24  
{
19  
{
25  
    static pool p;
20  
    static pool p;
26  
    return p;
21  
    return p;
27  
}
22  
}
28  

23  

29  
std::mutex&
24  
std::mutex&
30  
recycling_memory_resource::global_mutex() noexcept
25  
recycling_memory_resource::global_mutex() noexcept
31  
{
26  
{
32  
    static std::mutex mtx;
27  
    static std::mutex mtx;
33  
    return mtx;
28  
    return mtx;
34  
}
29  
}
35  

30  

36  
void*
31  
void*
37 -
recycling_memory_resource::do_allocate(std::size_t bytes, std::size_t)
32 +
recycling_memory_resource::allocate_slow(
 
33 +
    std::size_t rounded, std::size_t idx)
38 -
    std::size_t rounded = round_up_pow2(bytes);
 
39 -
    std::size_t idx = get_class_index(rounded);
 
40 -

 
41 -
    if(idx >= num_classes)
 
42 -
        return ::operator new(bytes);
 
43 -

 
44 -
    if(auto* p = local().buckets[idx].pop())
 
45 -
        return p;
 
46 -

 
47  
{
34  
{
48  
    {
35  
    {
49  
        std::lock_guard<std::mutex> lock(global_mutex());
36  
        std::lock_guard<std::mutex> lock(global_mutex());
50  
        if(auto* p = global().buckets[idx].pop(local().buckets[idx]))
37  
        if(auto* p = global().buckets[idx].pop(local().buckets[idx]))
51  
            return p;
38  
            return p;
52 -

 
53  
    }
39  
    }
54  
    return ::operator new(rounded);
40  
    return ::operator new(rounded);
55  
}
41  
}
56  

42  

57  
void
43  
void
58 -
recycling_memory_resource::do_deallocate(void* p, std::size_t bytes, std::size_t)
44 +
recycling_memory_resource::deallocate_slow(
 
45 +
    void* p, std::size_t idx)
59 -
    std::size_t rounded = round_up_pow2(bytes);
 
60 -
    std::size_t idx = get_class_index(rounded);
 
61 -

 
62 -
    if(idx >= num_classes)
 
63 -
    {
 
64 -
        ::operator delete(p);
 
65 -
        return;
 
66 -
    }
 
67 -

 
68 -
    if(local().buckets[idx].push(p))
 
69 -
        return;
 
70 -

 
71  
{
46  
{
72  
    {
47  
    {
73  
        std::lock_guard<std::mutex> lock(global_mutex());
48  
        std::lock_guard<std::mutex> lock(global_mutex());
74  
        if(global().buckets[idx].push(p))
49  
        if(global().buckets[idx].push(p))
75  
            return;
50  
            return;
76 -

 
77  
    }
51  
    }
78  
    ::operator delete(p);
52  
    ::operator delete(p);
 
53 +
}
 
54 +

 
55 +
void*
 
56 +
recycling_memory_resource::do_allocate(std::size_t bytes, std::size_t alignment)
 
57 +
{
 
58 +
    return allocate_fast(bytes, alignment);
 
59 +
}
 
60 +

 
61 +
void
 
62 +
recycling_memory_resource::do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
 
63 +
{
 
64 +
    deallocate_fast(p, bytes, alignment);
79  
}
65  
}
80  

66  

81  
std::pmr::memory_resource*
67  
std::pmr::memory_resource*
82  
get_recycling_memory_resource() noexcept
68  
get_recycling_memory_resource() noexcept
83  
{
69  
{
84  
    static recycling_memory_resource instance;
70  
    static recycling_memory_resource instance;
85  
    return &instance;
71  
    return &instance;
86  
}
72  
}
87  

73  

88  
} // namespace capy
74  
} // namespace capy
89  
} // namespace boost
75  
} // namespace boost