Line data Source code
1 : #ifndef IPPL_BUFFER_HANDLER_HPP
2 : #define IPPL_BUFFER_HANDLER_HPP
3 :
4 : namespace ippl {
5 :
6 : template <typename MemorySpace>
7 5504 : DefaultBufferHandler<MemorySpace>::~DefaultBufferHandler() {}
8 :
9 : template <typename MemorySpace>
10 : typename DefaultBufferHandler<MemorySpace>::buffer_type
11 19492 : DefaultBufferHandler<MemorySpace>::getBuffer(size_type size, double overallocation) {
12 19492 : size_type requiredSize = static_cast<size_type>(size * overallocation);
13 :
14 19492 : auto freeBuffer = findFreeBuffer(requiredSize);
15 19492 : if (freeBuffer != nullptr) {
16 6438 : return getFreeBuffer(freeBuffer);
17 : }
18 :
19 13054 : if (!free_buffers.empty()) {
20 4 : return reallocateLargestFreeBuffer(requiredSize);
21 : }
22 :
23 13050 : return allocateNewBuffer(requiredSize);
24 19492 : }
25 :
26 : template <typename MemorySpace>
27 38 : void DefaultBufferHandler<MemorySpace>::freeBuffer(buffer_type buffer) {
28 38 : if (isBufferUsed(buffer)) {
29 36 : releaseUsedBuffer(buffer);
30 : }
31 38 : }
32 :
33 : template <typename MemorySpace>
34 1086 : void DefaultBufferHandler<MemorySpace>::freeAllBuffers() {
35 1086 : free_buffers.insert(used_buffers.begin(), used_buffers.end());
36 1086 : used_buffers.clear();
37 :
38 1086 : freeSize_m += usedSize_m;
39 1086 : usedSize_m = 0;
40 1086 : }
41 :
42 : template <typename MemorySpace>
43 62 : void DefaultBufferHandler<MemorySpace>::deleteAllBuffers() {
44 62 : freeSize_m = 0;
45 62 : usedSize_m = 0;
46 :
47 62 : used_buffers.clear();
48 62 : free_buffers.clear();
49 62 : }
50 :
51 : template <typename MemorySpace>
52 : typename DefaultBufferHandler<MemorySpace>::size_type
53 20590 : DefaultBufferHandler<MemorySpace>::getUsedSize() const {
54 20590 : return usedSize_m;
55 : }
56 :
57 : template <typename MemorySpace>
58 : typename DefaultBufferHandler<MemorySpace>::size_type
59 20590 : DefaultBufferHandler<MemorySpace>::getFreeSize() const {
60 20590 : return freeSize_m;
61 : }
62 :
63 : template <typename MemorySpace>
64 324265 : bool DefaultBufferHandler<MemorySpace>::bufferSizeComparator(const buffer_type& lhs,
65 : const buffer_type& rhs) {
66 324265 : if (lhs->getBufferSize() != rhs->getBufferSize()) {
67 95325 : return lhs->getBufferSize() < rhs->getBufferSize();
68 : }
69 :
70 : // Use memory address as a tie-breaker to enforce total ordering of buffers.
71 228940 : return lhs < rhs;
72 : }
73 :
74 : template <typename MemorySpace>
75 38 : bool DefaultBufferHandler<MemorySpace>::isBufferUsed(buffer_type buffer) const {
76 38 : return used_buffers.find(buffer) != used_buffers.end();
77 : }
78 :
79 : template <typename MemorySpace>
80 36 : void DefaultBufferHandler<MemorySpace>::releaseUsedBuffer(buffer_type buffer) {
81 36 : auto it = used_buffers.find(buffer);
82 :
83 36 : usedSize_m -= buffer->getBufferSize();
84 36 : freeSize_m += buffer->getBufferSize();
85 :
86 36 : used_buffers.erase(it);
87 36 : free_buffers.insert(buffer);
88 36 : }
89 :
90 : template <typename MemorySpace>
91 : typename DefaultBufferHandler<MemorySpace>::buffer_type
92 19492 : DefaultBufferHandler<MemorySpace>::findFreeBuffer(size_type requiredSize) {
93 19492 : auto it = findSmallestSufficientBuffer(requiredSize);
94 19492 : if (it != free_buffers.end()) {
95 6438 : return *it;
96 : }
97 13054 : return nullptr;
98 : }
99 :
100 : template <typename MemorySpace>
101 : typename DefaultBufferHandler<MemorySpace>::buffer_set_type::iterator
102 19492 : DefaultBufferHandler<MemorySpace>::findSmallestSufficientBuffer(size_type requiredSize) {
103 19492 : return std::find_if(free_buffers.begin(), free_buffers.end(),
104 855626 : [requiredSize](const buffer_type& buffer) {
105 855626 : return buffer->getBufferSize() >= requiredSize;
106 19492 : });
107 : }
108 :
109 : template <typename MemorySpace>
110 : typename DefaultBufferHandler<MemorySpace>::buffer_type
111 6438 : DefaultBufferHandler<MemorySpace>::getFreeBuffer(buffer_type buffer) {
112 6438 : freeSize_m -= buffer->getBufferSize();
113 6438 : usedSize_m += buffer->getBufferSize();
114 :
115 6438 : free_buffers.erase(buffer);
116 6438 : used_buffers.insert(buffer);
117 6438 : return buffer;
118 : }
119 :
120 : template <typename MemorySpace>
121 : typename DefaultBufferHandler<MemorySpace>::buffer_type
122 4 : DefaultBufferHandler<MemorySpace>::reallocateLargestFreeBuffer(size_type requiredSize) {
123 4 : auto largest_it = std::prev(free_buffers.end());
124 4 : buffer_type buffer = *largest_it;
125 :
126 4 : freeSize_m -= buffer->getBufferSize();
127 4 : usedSize_m += requiredSize;
128 :
129 4 : free_buffers.erase(buffer);
130 4 : buffer->reallocBuffer(requiredSize);
131 :
132 4 : used_buffers.insert(buffer);
133 4 : return buffer;
134 0 : }
135 :
136 : template <typename MemorySpace>
137 : typename DefaultBufferHandler<MemorySpace>::buffer_type
138 13050 : DefaultBufferHandler<MemorySpace>::allocateNewBuffer(size_type requiredSize) {
139 13050 : buffer_type newBuffer = std::make_shared<archive_type>(requiredSize);
140 :
141 13050 : usedSize_m += newBuffer->getBufferSize();
142 13050 : used_buffers.insert(newBuffer);
143 13050 : return newBuffer;
144 0 : }
145 :
146 : } // namespace ippl
147 :
148 : #endif
|