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