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 3560 : 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 839 : void DefaultBufferHandler<MemorySpace>::deleteAllBuffers() {
44 839 : freeSize_m = 0;
45 839 : usedSize_m = 0;
46 :
47 839 : used_buffers.clear();
48 839 : free_buffers.clear();
49 839 : }
50 :
51 : template <typename MemorySpace>
52 : typename DefaultBufferHandler<MemorySpace>::size_type
53 855 : DefaultBufferHandler<MemorySpace>::getUsedSize() const {
54 855 : return usedSize_m;
55 : }
56 :
57 : template <typename MemorySpace>
58 : typename DefaultBufferHandler<MemorySpace>::size_type
59 855 : DefaultBufferHandler<MemorySpace>::getFreeSize() const {
60 855 : 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
|