1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2007 - 2019 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15
16 #ifndef dealii_vector_memory_templates_h
17 #define dealii_vector_memory_templates_h
18
19
20 #include <deal.II/base/config.h>
21
22 #include <deal.II/base/memory_consumption.h>
23
24 #include <deal.II/lac/vector_memory.h>
25
26 #include <memory>
27
28 DEAL_II_NAMESPACE_OPEN
29
30
31 template <typename VectorType>
32 typename GrowingVectorMemory<VectorType>::Pool &
get_pool()33 GrowingVectorMemory<VectorType>::get_pool()
34 {
35 static GrowingVectorMemory<VectorType>::Pool pool;
36 return pool;
37 }
38
39
40
41 template <typename VectorType>
42 Threads::Mutex GrowingVectorMemory<VectorType>::mutex;
43
44
45
46 template <typename VectorType>
Pool()47 inline GrowingVectorMemory<VectorType>::Pool::Pool()
48 : data(nullptr)
49 {}
50
51
52
53 template <typename VectorType>
~Pool()54 inline GrowingVectorMemory<VectorType>::Pool::~Pool()
55 {
56 // Nothing to do if memory was unused.
57 if (data == nullptr)
58 return;
59
60 // delete the 'data' object. this also releases all vectors
61 // that are pointed to by the std::unique_ptrs
62 data->clear();
63 delete data;
64 }
65
66
67 template <typename VectorType>
68 inline void
initialize(const size_type size)69 GrowingVectorMemory<VectorType>::Pool::initialize(const size_type size)
70 {
71 if (data == nullptr)
72 {
73 data = new std::vector<entry_type>(size);
74
75 for (typename std::vector<entry_type>::iterator i = data->begin();
76 i != data->end();
77 ++i)
78 {
79 i->first = false;
80 i->second = std::make_unique<VectorType>();
81 }
82 }
83 }
84
85
86 template <typename VectorType>
GrowingVectorMemory(const size_type initial_size,const bool log_statistics)87 inline GrowingVectorMemory<VectorType>::GrowingVectorMemory(
88 const size_type initial_size,
89 const bool log_statistics)
90
91 : total_alloc(0)
92 , current_alloc(0)
93 , log_statistics(log_statistics)
94 {
95 std::lock_guard<std::mutex> lock(mutex);
96 get_pool().initialize(initial_size);
97 }
98
99
100 template <typename VectorType>
~GrowingVectorMemory()101 inline GrowingVectorMemory<VectorType>::~GrowingVectorMemory()
102 {
103 AssertNothrow(current_alloc == 0,
104 StandardExceptions::ExcMemoryLeak(current_alloc));
105 if (log_statistics)
106 {
107 deallog << "GrowingVectorMemory:Overall allocated vectors: "
108 << total_alloc << std::endl;
109 deallog << "GrowingVectorMemory:Maximum allocated vectors: "
110 << get_pool().data->size() << std::endl;
111 }
112 }
113
114
115
116 template <typename VectorType>
117 inline VectorType *
alloc()118 GrowingVectorMemory<VectorType>::alloc()
119 {
120 std::lock_guard<std::mutex> lock(mutex);
121
122 ++total_alloc;
123 ++current_alloc;
124 // see if there is a free vector
125 // available in our list
126 for (typename std::vector<entry_type>::iterator i = get_pool().data->begin();
127 i != get_pool().data->end();
128 ++i)
129 {
130 if (i->first == false)
131 {
132 i->first = true;
133 return i->second.get();
134 }
135 }
136
137 // no free vector found, so let's just allocate a new one
138 get_pool().data->emplace_back(true, std::make_unique<VectorType>());
139
140 return get_pool().data->back().second.get();
141 }
142
143
144
145 template <typename VectorType>
146 inline void
free(const VectorType * const v)147 GrowingVectorMemory<VectorType>::free(const VectorType *const v)
148 {
149 std::lock_guard<std::mutex> lock(mutex);
150
151 for (typename std::vector<entry_type>::iterator i = get_pool().data->begin();
152 i != get_pool().data->end();
153 ++i)
154 {
155 if (v == i->second.get())
156 {
157 i->first = false;
158 --current_alloc;
159 return;
160 }
161 }
162 Assert(false, typename VectorMemory<VectorType>::ExcNotAllocatedHere());
163 }
164
165
166
167 template <typename VectorType>
168 inline void
release_unused_memory()169 GrowingVectorMemory<VectorType>::release_unused_memory()
170 {
171 std::lock_guard<std::mutex> lock(mutex);
172
173 if (get_pool().data != nullptr)
174 get_pool().data->clear();
175 }
176
177
178
179 template <typename VectorType>
180 inline std::size_t
memory_consumption()181 GrowingVectorMemory<VectorType>::memory_consumption() const
182 {
183 std::lock_guard<std::mutex> lock(mutex);
184
185 std::size_t result = sizeof(*this);
186 const typename std::vector<entry_type>::const_iterator end =
187 get_pool().data->end();
188 for (typename std::vector<entry_type>::const_iterator i =
189 get_pool().data->begin();
190 i != end;
191 ++i)
192 result += sizeof(*i) + MemoryConsumption::memory_consumption(i->second);
193
194 return result;
195 }
196
197
198 DEAL_II_NAMESPACE_CLOSE
199
200 #endif
201