Line data Source code
1 : /*
2 : * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG__page_container_impl__
34 : #define __H__UG__page_container_impl__
35 :
36 : #include <algorithm>
37 : #include "page_container.h"
38 :
39 : // a temporary include
40 : #include "common/log.h"
41 :
42 : namespace ug
43 : {
44 :
45 : template <class T, int MAX_PAGE_SIZE, class Allocator>
46 0 : PageContainer<T, MAX_PAGE_SIZE, Allocator>::
47 : PageContainer() :
48 0 : m_numPageEntries((size_t)(MAX_PAGE_SIZE / sizeof(T))),
49 0 : m_size(0)
50 : {
51 : }
52 :
53 : template <class T, int MAX_PAGE_SIZE, class Allocator>
54 : PageContainer<T, MAX_PAGE_SIZE, Allocator>::
55 : PageContainer(const PageContainer& pc) :
56 : m_numPageEntries((size_t)(MAX_PAGE_SIZE / sizeof(T)))
57 : {
58 : assign_container(pc);
59 : }
60 :
61 : template <class T, int MAX_PAGE_SIZE, class Allocator>
62 0 : PageContainer<T, MAX_PAGE_SIZE, Allocator>::
63 : ~PageContainer()
64 : {
65 : clear();
66 0 : for(size_t i = 0; i < m_pages.size(); ++i){
67 0 : m_alloc.deallocate(m_pages[i], m_numPageEntries);
68 : }
69 0 : }
70 :
71 : template <class T, int MAX_PAGE_SIZE, class Allocator>
72 : PageContainer<T, MAX_PAGE_SIZE, Allocator>&
73 : PageContainer<T, MAX_PAGE_SIZE, Allocator>::
74 : operator=(const PageContainer& pc)
75 : {
76 : assign_container(pc);
77 : return *this;
78 : }
79 :
80 : template <class T, int MAX_PAGE_SIZE, class Allocator>
81 : size_t PageContainer<T, MAX_PAGE_SIZE, Allocator>::
82 : size() const
83 : {
84 : return m_size;
85 : }
86 :
87 : template <class T, int MAX_PAGE_SIZE, class Allocator>
88 : size_t PageContainer<T, MAX_PAGE_SIZE, Allocator>::
89 : capacity() const
90 : {
91 : return m_pages.size() * m_numPageEntries;
92 : }
93 :
94 : template <class T, int MAX_PAGE_SIZE, class Allocator>
95 0 : void PageContainer<T, MAX_PAGE_SIZE, Allocator>::
96 : resize(size_t size, const T& val)
97 : {
98 : using namespace std;
99 : //UG_LOG(" reserving...\n");
100 : // allocate memory
101 0 : reserve(size);
102 : //UG_LOG(" constructing...\n");
103 : // call constructor on new objects
104 : // to do this with optimal performance,
105 : // we'll iterate over the pages directly
106 0 : while(m_size < size){
107 : T* page = get_page(m_size);
108 : size_t offset = get_page_offset(m_size);
109 0 : const size_t maxI = min(m_numPageEntries, offset + size - m_size);
110 :
111 0 : for(size_t i = offset; i < maxI; ++i)
112 0 : m_alloc.construct(page + i, val);
113 :
114 0 : m_size += maxI - offset;
115 : }
116 : //UG_LOG(" destroying...\n");
117 : // if resize shrinks the data array, we have to call the destructors of
118 : // deleted objects. At this point size <= m_size.
119 0 : while(m_size > size){
120 0 : T* page = get_page(m_size - 1);
121 0 : size_t maxI = get_page_offset(m_size - 1) + 1;
122 : size_t minI = 0;
123 0 : const size_t diff = m_size - size;
124 0 : if(maxI > diff)
125 0 : minI = (maxI) - diff;
126 :
127 : for(size_t i = minI; i < maxI; ++i)
128 : m_alloc.destroy(page + i);
129 :
130 0 : m_size -= (maxI - minI);
131 : }
132 : //UG_LOG(" done...\n");
133 0 : }
134 :
135 : template <class T, int MAX_PAGE_SIZE, class Allocator>
136 0 : void PageContainer<T, MAX_PAGE_SIZE, Allocator>::
137 : reserve(size_t size)
138 : {
139 : using namespace std;
140 :
141 : //UG_LOG("*num page entries: " << m_numPageEntries << ", required size: " << size << endl);
142 0 : while(m_pages.size() * m_numPageEntries < size){
143 : //UG_LOG("**allocating " << m_numPageEntries << " elems of size " << sizeof(T) << endl);
144 0 : T* buf = m_alloc.allocate(m_numPageEntries);
145 : //UG_LOG("**adding a new page (current num pages: " << m_pages.size() << ")\n");
146 0 : m_pages.push_back(buf);
147 : }
148 : //UG_LOG("*done\n");
149 0 : }
150 :
151 : template <class T, int MAX_PAGE_SIZE, class Allocator>
152 : void PageContainer<T, MAX_PAGE_SIZE, Allocator>::
153 : clear()
154 : {
155 0 : resize(0);
156 : }
157 :
158 : template <class T, int MAX_PAGE_SIZE, class Allocator>
159 : T& PageContainer<T, MAX_PAGE_SIZE, Allocator>::
160 : operator[](size_t ind)
161 : {
162 : assert(ind < m_size);
163 0 : return get_page(ind)[get_page_offset(ind)];
164 : }
165 :
166 : template <class T, int MAX_PAGE_SIZE, class Allocator>
167 : const T& PageContainer<T, MAX_PAGE_SIZE, Allocator>::
168 : operator[](size_t ind) const
169 : {
170 : assert(ind < m_size);
171 : return get_page(ind)[get_page_offset(ind)];
172 : }
173 :
174 : template <class T, int MAX_PAGE_SIZE, class Allocator>
175 : void PageContainer<T, MAX_PAGE_SIZE, Allocator>::
176 : swap(PageContainer& pc)
177 : {
178 : m_pages.swap(pc.m_pages);
179 : Allocator talloc = m_alloc;
180 : m_alloc = pc.m_alloc;
181 : pc.m_alloc = talloc;
182 :
183 : size_t tmp = m_size;
184 : m_size = pc.m_size;
185 : pc.m_size = tmp;
186 : }
187 :
188 : template <class T, int MAX_PAGE_SIZE, class Allocator>
189 : void PageContainer<T, MAX_PAGE_SIZE, Allocator>::
190 : assign_container(const PageContainer& pc)
191 : {
192 : using namespace std;
193 : clear();
194 :
195 : reserve(pc.m_size);
196 :
197 : // copy all entries with optimal performance
198 : while(m_size < pc.m_size){
199 : T* page = get_page(m_size);
200 : T* srcPage = pc.get_page(m_size);
201 : size_t offset = get_page_offset(m_size);
202 : const size_t maxI = min(m_numPageEntries, offset + pc.m_size - m_size);
203 :
204 : for(size_t i = offset; i < maxI; ++i)
205 : m_alloc.construct(page + i, srcPage[i]);
206 :
207 : m_size += maxI;
208 : }
209 : }
210 :
211 : template <class T, int MAX_PAGE_SIZE, class Allocator>
212 : inline T* PageContainer<T, MAX_PAGE_SIZE, Allocator>::
213 : get_page(size_t ind) const
214 : {
215 : assert(get_page_index(ind) < m_pages.size());
216 0 : return m_pages[get_page_index(ind)];
217 : }
218 :
219 : template <class T, int MAX_PAGE_SIZE, class Allocator>
220 : inline size_t PageContainer<T, MAX_PAGE_SIZE, Allocator>::
221 : get_page_index(size_t ind) const
222 : {
223 0 : return ind / m_numPageEntries;
224 : }
225 :
226 : template <class T, int MAX_PAGE_SIZE, class Allocator>
227 : inline size_t PageContainer<T, MAX_PAGE_SIZE, Allocator>::
228 : get_page_offset(size_t ind) const
229 : {
230 0 : return ind % m_numPageEntries;
231 : }
232 :
233 : }// end of namespace
234 :
235 : #endif
|