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 6152 : DefaultBufferHandler<MemorySpace>::~DefaultBufferHandler() {}
8 :
9 : template <typename MemorySpace>
10 : typename DefaultBufferHandler<MemorySpace>::buffer_type
11 19540 : DefaultBufferHandler<MemorySpace>::getBuffer(size_type size, double overallocation) {
12 19540 : size_type requiredSize = static_cast<size_type>(size * overallocation);
13 :
14 19540 : auto freeBuffer = findFreeBuffer(requiredSize);
15 19540 : if (freeBuffer != nullptr) {
16 6470 : return getFreeBuffer(freeBuffer);
17 : }
18 :
19 13070 : if (!free_buffers.empty()) {
20 8 : return reallocateLargestFreeBuffer(requiredSize);
21 : }
22 :
23 13062 : return allocateNewBuffer(requiredSize);
24 19540 : }
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 1106 : void DefaultBufferHandler<MemorySpace>::freeAllBuffers() {
35 1106 : free_buffers.insert(used_buffers.begin(), used_buffers.end());
36 1106 : used_buffers.clear();
37 :
38 1106 : freeSize_m += usedSize_m;
39 1106 : usedSize_m = 0;
40 1106 : }
41 :
42 : template <typename MemorySpace>
43 66 : void DefaultBufferHandler<MemorySpace>::deleteAllBuffers() {
44 66 : freeSize_m = 0;
45 66 : usedSize_m = 0;
46 :
47 66 : used_buffers.clear();
48 66 : free_buffers.clear();
49 66 : }
50 :
51 : template <typename MemorySpace>
52 : typename DefaultBufferHandler<MemorySpace>::size_type
53 20662 : DefaultBufferHandler<MemorySpace>::getUsedSize() const {
54 20662 : return usedSize_m;
55 : }
56 :
57 : template <typename MemorySpace>
58 : typename DefaultBufferHandler<MemorySpace>::size_type
59 20662 : DefaultBufferHandler<MemorySpace>::getFreeSize() const {
60 20662 : return freeSize_m;
61 : }
62 :
63 : template <typename MemorySpace>
64 324309 : bool DefaultBufferHandler<MemorySpace>::bufferSizeComparator(const buffer_type& lhs,
65 : const buffer_type& rhs) {
66 324309 : if (lhs->getBufferSize() != rhs->getBufferSize()) {
67 94988 : return lhs->getBufferSize() < rhs->getBufferSize();
68 : }
69 :
70 : // Use memory address as a tie-breaker to enforce total ordering of buffers.
71 229321 : 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 19540 : DefaultBufferHandler<MemorySpace>::findFreeBuffer(size_type requiredSize) {
93 19540 : auto it = findSmallestSufficientBuffer(requiredSize);
94 19540 : if (it != free_buffers.end()) {
95 6470 : return *it;
96 : }
97 13070 : return nullptr;
98 : }
99 :
100 : template <typename MemorySpace>
101 : typename DefaultBufferHandler<MemorySpace>::buffer_set_type::iterator
102 19540 : DefaultBufferHandler<MemorySpace>::findSmallestSufficientBuffer(size_type requiredSize) {
103 19540 : return std::find_if(free_buffers.begin(), free_buffers.end(),
104 855668 : [requiredSize](const buffer_type& buffer) {
105 855668 : return buffer->getBufferSize() >= requiredSize;
106 19540 : });
107 : }
108 :
109 : template <typename MemorySpace>
110 : typename DefaultBufferHandler<MemorySpace>::buffer_type
111 6470 : DefaultBufferHandler<MemorySpace>::getFreeBuffer(buffer_type buffer) {
112 6470 : freeSize_m -= buffer->getBufferSize();
113 6470 : usedSize_m += buffer->getBufferSize();
114 :
115 6470 : free_buffers.erase(buffer);
116 6470 : used_buffers.insert(buffer);
117 6470 : return buffer;
118 : }
119 :
120 : template <typename MemorySpace>
121 : typename DefaultBufferHandler<MemorySpace>::buffer_type
122 8 : DefaultBufferHandler<MemorySpace>::reallocateLargestFreeBuffer(size_type requiredSize) {
123 8 : auto largest_it = std::prev(free_buffers.end());
124 8 : buffer_type buffer = *largest_it;
125 :
126 8 : freeSize_m -= buffer->getBufferSize();
127 8 : usedSize_m += requiredSize;
128 :
129 8 : free_buffers.erase(buffer);
130 8 : buffer->reallocBuffer(requiredSize);
131 :
132 8 : used_buffers.insert(buffer);
133 8 : return buffer;
134 0 : }
135 :
136 : template <typename MemorySpace>
137 : typename DefaultBufferHandler<MemorySpace>::buffer_type
138 13062 : DefaultBufferHandler<MemorySpace>::allocateNewBuffer(size_type requiredSize) {
139 13062 : buffer_type newBuffer = std::make_shared<archive_type>(requiredSize);
140 :
141 13062 : usedSize_m += newBuffer->getBufferSize();
142 13062 : used_buffers.insert(newBuffer);
143 13062 : return newBuffer;
144 0 : }
145 :
146 : } // namespace ippl
147 :
148 : #endif
|