Line data Source code
1 : #ifndef IPPL_BUFFER_HANDLER_H
2 : #define IPPL_BUFFER_HANDLER_H
3 :
4 : #include <memory>
5 : #include <set>
6 :
7 : #include "Communicate/Archive.h"
8 :
9 : namespace ippl {
10 :
11 : /**
12 : * @brief Interface for memory buffer handling.
13 : *
14 : * Defines methods for acquiring, freeing, and managing memory buffers.
15 : * Implementations are responsible for managing buffers efficiently,
16 : * ensuring that allocated buffers are reused where possible.
17 : *
18 : * @tparam MemorySpace The memory space type used for buffer allocation.
19 : */
20 : template <typename MemorySpace>
21 : class BufferHandler {
22 : public:
23 : using archive_type = ippl::detail::Archive<MemorySpace>;
24 : using buffer_type = std::shared_ptr<archive_type>;
25 : using size_type = ippl::detail::size_type;
26 :
27 8100 : virtual ~BufferHandler() {}
28 :
29 : /**
30 : * @brief Requests a memory buffer of a specified size.
31 : *
32 : * Provides a buffer of at least the specified size, with the option
33 : * to allocate additional space based on an overallocation multiplier.
34 : * This function attempts to reuse available buffers if possible.
35 : *
36 : * @param size The required size of the buffer, in bytes.
37 : * @param overallocation A multiplier to allocate extra space, which may help
38 : * avoid frequent reallocation in some use cases.
39 : * @return A shared pointer to the allocated buffer.
40 : */
41 : virtual buffer_type getBuffer(size_type size, double overallocation) = 0;
42 :
43 : /**
44 : * @brief Frees a specified buffer.
45 : *
46 : * Moves the specified buffer to a free state, making it available
47 : * for reuse in future buffer requests.
48 : *
49 : * @param buffer The buffer to be freed.
50 : */
51 : virtual void freeBuffer(buffer_type buffer) = 0;
52 :
53 : /**
54 : * @brief Frees all currently used buffers.
55 : *
56 : * Transfers all used buffers to the free state, making them available
57 : * for reuse. This does not deallocate memory but resets buffer usage.
58 : */
59 : virtual void freeAllBuffers() = 0;
60 :
61 : /**
62 : * @brief Deletes all buffers.
63 : *
64 : * Releases all allocated memory buffers, both used and free.
65 : * After this call, no buffers are available until new allocations.
66 : */
67 : virtual void deleteAllBuffers() = 0;
68 :
69 : /**
70 : * @brief Gets the size of all buffers in use.
71 : *
72 : * @return Total size of buffers that are in use in bytes.
73 : */
74 : virtual size_type getUsedSize() const = 0;
75 :
76 : /**
77 : * @brief Gets the size of all free buffers.
78 : *
79 : * @return Total size of free buffers in bytes.
80 : */
81 : virtual size_type getFreeSize() const = 0;
82 : };
83 :
84 : /**
85 : * @class DefaultBufferHandler
86 : * @brief Concrete implementation of BufferHandler for managing memory buffers.
87 : *
88 : * This class implements the BufferHandler interface, providing concrete behavior for
89 : * buffer allocation, freeing, and memory management. It maintains two sorted sets of free and
90 : * in-use buffers to allow for efficient queries.
91 : *
92 : * @tparam MemorySpace The memory space type for the buffer (e.g., `Kokkos::HostSpace`).
93 : */
94 : template <typename MemorySpace>
95 : class DefaultBufferHandler : public BufferHandler<MemorySpace> {
96 : public:
97 : using typename BufferHandler<MemorySpace>::archive_type;
98 : using typename BufferHandler<MemorySpace>::buffer_type;
99 : using typename BufferHandler<MemorySpace>::size_type;
100 :
101 : ~DefaultBufferHandler() override;
102 :
103 : /**
104 : * @brief Acquires a buffer of at least the specified size.
105 : *
106 : * Requests a memory buffer of the specified size, with the option
107 : * to request a buffer larger than the base size by an overallocation
108 : * multiplier. If a sufficiently large buffer is available, it is returned. If not, the
109 : * largest free buffer is reallocated. If there are no free buffers available, only then a
110 : * new buffer is allocated.
111 : *
112 : * @param size The required buffer size.
113 : * @param overallocation A multiplier to allocate additional buffer space.
114 : * @return A shared pointer to the allocated buffer.
115 : */
116 : buffer_type getBuffer(size_type size, double overallocation) override;
117 :
118 : /**
119 : * @copydoc BufferHandler::freeBuffer
120 : */
121 : void freeBuffer(buffer_type buffer) override;
122 :
123 : /**
124 : * @copydoc BufferHandler::freeBuffer
125 : */
126 : void freeAllBuffers() override;
127 :
128 : /**
129 : * @copydoc BufferHandler::freeBuffer
130 : */
131 : void deleteAllBuffers() override;
132 :
133 : /**
134 : * @copydoc BufferHandler::freeBuffer
135 : */
136 : size_type getUsedSize() const override;
137 :
138 : /**
139 : * @copydoc BufferHandler::freeBuffer
140 : */
141 : size_type getFreeSize() const override;
142 :
143 : private:
144 : using buffer_comparator_type = bool (*)(const buffer_type&, const buffer_type&);
145 : using buffer_set_type = std::set<buffer_type, buffer_comparator_type>;
146 :
147 : static bool bufferSizeComparator(const buffer_type& lhs, const buffer_type& rhs);
148 :
149 : bool isBufferUsed(buffer_type buffer) const;
150 : void releaseUsedBuffer(buffer_type buffer);
151 : buffer_type findFreeBuffer(size_type requiredSize);
152 : buffer_set_type::iterator findSmallestSufficientBuffer(size_type requiredSize);
153 : buffer_type getFreeBuffer(buffer_type buffer);
154 : buffer_type reallocateLargestFreeBuffer(size_type requiredSize);
155 : buffer_type allocateNewBuffer(size_type requiredSize);
156 :
157 : size_type usedSize_m; ///< Total size of all allocated buffers
158 : size_type freeSize_m; ///< Total size of all free buffers
159 :
160 : protected:
161 : buffer_set_type used_buffers{
162 : &DefaultBufferHandler::bufferSizeComparator}; ///< Set of used buffers
163 : buffer_set_type free_buffers{
164 : &DefaultBufferHandler::bufferSizeComparator}; ///< Set of free buffers
165 : };
166 : } // namespace ippl
167 :
168 : #include "Communicate/BufferHandler.hpp"
169 :
170 : #endif
|