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::pool&
16  
recycling_memory_resource::local() noexcept
16  
recycling_memory_resource::local() noexcept
17  
{
17  
{
18  
    static thread_local pool p;
18  
    static thread_local pool p;
19  
    return p;
19  
    return p;
20  
}
20  
}
21  

21  

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

28  

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

35  

36  
void*
36  
void*
37  
recycling_memory_resource::do_allocate(std::size_t bytes, std::size_t)
37  
recycling_memory_resource::do_allocate(std::size_t bytes, std::size_t)
38  
{
38  
{
39  
    std::size_t rounded = round_up_pow2(bytes);
39  
    std::size_t rounded = round_up_pow2(bytes);
40  
    std::size_t idx = get_class_index(rounded);
40  
    std::size_t idx = get_class_index(rounded);
41  

41  

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

44  

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

47  

48  
    {
48  
    {
49  
        std::lock_guard<std::mutex> lock(global_mutex());
49  
        std::lock_guard<std::mutex> lock(global_mutex());
50  
        if(auto* p = global().buckets[idx].pop(local().buckets[idx]))
50  
        if(auto* p = global().buckets[idx].pop(local().buckets[idx]))
51  
            return p;
51  
            return p;
52  
    }
52  
    }
53  

53  

54  
    return ::operator new(rounded);
54  
    return ::operator new(rounded);
55  
}
55  
}
56  

56  

57  
void
57  
void
58  
recycling_memory_resource::do_deallocate(void* p, std::size_t bytes, std::size_t)
58  
recycling_memory_resource::do_deallocate(void* p, std::size_t bytes, std::size_t)
59  
{
59  
{
60  
    std::size_t rounded = round_up_pow2(bytes);
60  
    std::size_t rounded = round_up_pow2(bytes);
61  
    std::size_t idx = get_class_index(rounded);
61  
    std::size_t idx = get_class_index(rounded);
62  

62  

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

68  

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

71  

72  
    {
72  
    {
73  
        std::lock_guard<std::mutex> lock(global_mutex());
73  
        std::lock_guard<std::mutex> lock(global_mutex());
74  
        if(global().buckets[idx].push(p))
74  
        if(global().buckets[idx].push(p))
75  
            return;
75  
            return;
76  
    }
76  
    }
77  

77  

78  
    ::operator delete(p);
78  
    ::operator delete(p);
79  
}
79  
}
80  

80  

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

87  

88  
} // namespace capy
88  
} // namespace capy
89  
} // namespace boost
89  
} // namespace boost