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::~recycling_memory_resource() = default;
15  
recycling_memory_resource::~recycling_memory_resource() = default;
16  

16  

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

23  

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

30  

31  
void*
31  
void*
32  
recycling_memory_resource::allocate_slow(
32  
recycling_memory_resource::allocate_slow(
33  
    std::size_t rounded, std::size_t idx)
33  
    std::size_t rounded, std::size_t idx)
34  
{
34  
{
35  
    {
35  
    {
36  
        std::lock_guard<std::mutex> lock(global_mutex());
36  
        std::lock_guard<std::mutex> lock(global_mutex());
37  
        if(auto* p = global().buckets[idx].pop(local().buckets[idx]))
37  
        if(auto* p = global().buckets[idx].pop(local().buckets[idx]))
38  
            return p;
38  
            return p;
39  
    }
39  
    }
40  
    return ::operator new(rounded);
40  
    return ::operator new(rounded);
41  
}
41  
}
42  

42  

43  
void
43  
void
44  
recycling_memory_resource::deallocate_slow(
44  
recycling_memory_resource::deallocate_slow(
45  
    void* p, std::size_t idx)
45  
    void* p, std::size_t idx)
46  
{
46  
{
47  
    {
47  
    {
48  
        std::lock_guard<std::mutex> lock(global_mutex());
48  
        std::lock_guard<std::mutex> lock(global_mutex());
49  
        if(global().buckets[idx].push(p))
49  
        if(global().buckets[idx].push(p))
50  
            return;
50  
            return;
51  
    }
51  
    }
52  
    ::operator delete(p);
52  
    ::operator delete(p);
53  
}
53  
}
54  

54  

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

60  

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

66  

67  
std::pmr::memory_resource*
67  
std::pmr::memory_resource*
68  
get_recycling_memory_resource() noexcept
68  
get_recycling_memory_resource() noexcept
69  
{
69  
{
70  
    static recycling_memory_resource instance;
70  
    static recycling_memory_resource instance;
71  
    return &instance;
71  
    return &instance;
72  
}
72  
}
73  

73  

74  
} // namespace capy
74  
} // namespace capy
75  
} // namespace boost
75  
} // namespace boost