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 3896 : DefaultBufferHandler<MemorySpace>::~DefaultBufferHandler() {}
8 :
9 : template <typename MemorySpace>
10 : typename DefaultBufferHandler<MemorySpace>::buffer_type
11 18740 : DefaultBufferHandler<MemorySpace>::getBuffer(size_type size, double overallocation) {
12 18740 : size_type requiredSize = static_cast<size_type>(size * overallocation);
13 :
14 18740 : auto freeBuffer = findFreeBuffer(requiredSize);
15 18740 : if (freeBuffer != nullptr) {
16 6198 : return getFreeBuffer(freeBuffer);
17 : }
18 :
19 12542 : if (!free_buffers.empty()) {
20 4 : return reallocateLargestFreeBuffer(requiredSize);
21 : }
22 :
23 12538 : return allocateNewBuffer(requiredSize);
24 18740 : }
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 638 : void DefaultBufferHandler<MemorySpace>::freeAllBuffers() {
35 638 : free_buffers.insert(used_buffers.begin(), used_buffers.end());
36 638 : used_buffers.clear();
37 :
38 638 : freeSize_m += usedSize_m;
39 638 : usedSize_m = 0;
40 638 : }
41 :
42 : template <typename MemorySpace>
43 50 : void DefaultBufferHandler<MemorySpace>::deleteAllBuffers() {
44 50 : freeSize_m = 0;
45 50 : usedSize_m = 0;
46 :
47 50 : used_buffers.clear();
48 50 : free_buffers.clear();
49 50 : }
50 :
51 : template <typename MemorySpace>
52 : typename DefaultBufferHandler<MemorySpace>::size_type
53 19378 : DefaultBufferHandler<MemorySpace>::getUsedSize() const {
54 19378 : return usedSize_m;
55 : }
56 :
57 : template <typename MemorySpace>
58 : typename DefaultBufferHandler<MemorySpace>::size_type
59 19378 : DefaultBufferHandler<MemorySpace>::getFreeSize() const {
60 19378 : return freeSize_m;
61 : }
62 :
63 : template <typename MemorySpace>
64 321406 : bool DefaultBufferHandler<MemorySpace>::bufferSizeComparator(const buffer_type& lhs,
65 : const buffer_type& rhs) {
66 321406 : if (lhs->getBufferSize() != rhs->getBufferSize()) {
67 94477 : return lhs->getBufferSize() < rhs->getBufferSize();
68 : }
69 :
70 : // Use memory address as a tie-breaker to enforce total ordering of buffers.
71 226929 : 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 18740 : DefaultBufferHandler<MemorySpace>::findFreeBuffer(size_type requiredSize) {
93 18740 : auto it = findSmallestSufficientBuffer(requiredSize);
94 18740 : if (it != free_buffers.end()) {
95 6198 : return *it;
96 : }
97 12542 : return nullptr;
98 : }
99 :
100 : template <typename MemorySpace>
101 : typename DefaultBufferHandler<MemorySpace>::buffer_set_type::iterator
102 18740 : DefaultBufferHandler<MemorySpace>::findSmallestSufficientBuffer(size_type requiredSize) {
103 18740 : return std::find_if(free_buffers.begin(), free_buffers.end(),
104 855386 : [requiredSize](const buffer_type& buffer) {
105 855386 : return buffer->getBufferSize() >= requiredSize;
106 18740 : });
107 : }
108 :
109 : template <typename MemorySpace>
110 : typename DefaultBufferHandler<MemorySpace>::buffer_type
111 6198 : DefaultBufferHandler<MemorySpace>::getFreeBuffer(buffer_type buffer) {
112 6198 : freeSize_m -= buffer->getBufferSize();
113 6198 : usedSize_m += buffer->getBufferSize();
114 :
115 6198 : free_buffers.erase(buffer);
116 6198 : used_buffers.insert(buffer);
117 6198 : 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 12538 : DefaultBufferHandler<MemorySpace>::allocateNewBuffer(size_type requiredSize) {
139 12538 : buffer_type newBuffer = std::make_shared<archive_type>(requiredSize);
140 :
141 12538 : usedSize_m += newBuffer->getBufferSize();
142 12538 : used_buffers.insert(newBuffer);
143 12538 : return newBuffer;
144 0 : }
145 :
146 : } // namespace ippl
147 :
148 : #endif
|