Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dune-istl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Core Modules
dune-istl
Commits
aab39c5a
Commit
aab39c5a
authored
6 years ago
by
Lasse Hinrichsen-Bischoff
Committed by
Simon Praetorius
10 months ago
Browse files
Options
Downloads
Patches
Plain Diff
[VariableBlockVector] Use std::vector for memory management
parent
f37f90ae
No related branches found
No related tags found
1 merge request
!463
Cleanup the VariableBlockVector implementation
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
dune/istl/vbvector.hh
+77
-328
77 additions, 328 deletions
dune/istl/vbvector.hh
with
77 additions
and
328 deletions
dune/istl/vbvector.hh
+
77
−
328
View file @
aab39c5a
...
...
@@ -48,6 +48,9 @@ namespace Dune {
// just a shorthand
typedef
Imp
::
BlockVectorWindow
<
B
,
A
>
window_type
;
// data-structure holding the windows (butbut not the actual data)
using
VectorWindows
=
std
::
vector
<
window_type
,
typename
A
::
template
rebind
<
window_type
>
::
other
>
;
public:
//===== type definitions and constants
...
...
@@ -90,12 +93,7 @@ namespace Dune {
object cannot be used yet
*/
VariableBlockVector
()
:
Imp
::
block_vector_unmanaged
<
B
,
size_type
>
()
{
// nothing is known ...
nblocks
=
0
;
block
=
nullptr
;
initialized
=
false
;
}
{}
/** make vector with given number of blocks, but size of each block is not yet known,
object cannot be used yet
...
...
@@ -103,21 +101,7 @@ namespace Dune {
explicit
VariableBlockVector
(
size_type
_nblocks
)
:
Imp
::
block_vector_unmanaged
<
B
,
size_type
>
()
{
// we can allocate the windows now
nblocks
=
_nblocks
;
if
(
nblocks
>
0
)
{
block
=
windowAllocator_
.
allocate
(
nblocks
);
new
(
block
)
window_type
[
nblocks
];
}
else
{
nblocks
=
0
;
block
=
nullptr
;
}
// Note: memory in base class still not allocated
// the vector not usable
initialized
=
false
;
block
.
resize
(
_nblocks
);
}
/** make vector with given number of blocks each having a constant size,
...
...
@@ -129,133 +113,49 @@ namespace Dune {
VariableBlockVector
(
size_type
_nblocks
,
size_type
m
)
:
Imp
::
block_vector_unmanaged
<
B
,
size_type
>
()
{
// and we can allocate the big array in the base class
this
->
n
=
_nblocks
*
m
;
if
(
this
->
n
>
0
)
{
this
->
p
=
allocator_
.
allocate
(
this
->
n
);
new
(
this
->
p
)
B
[
this
->
n
];
}
else
{
this
->
n
=
0
;
this
->
p
=
nullptr
;
}
storage_
.
resize
(
_nblocks
*
m
);
syncBaseArray
();
// we can allocate the windows now
nblocks
=
_nblocks
;
if
(
nblocks
>
0
)
{
// allocate and construct the windows
block
=
windowAllocator_
.
allocate
(
nblocks
);
new
(
block
)
window_type
[
nblocks
];
block
.
resize
(
_nblocks
);
// set the windows into the big array
for
(
size_type
i
=
0
;
i
<
nblocks
;
++
i
)
block
[
i
].
set
(
m
,
this
->
p
+
(
i
*
m
));
}
else
{
nblocks
=
0
;
block
=
nullptr
;
}
// set the windows into the big array
for
(
size_type
i
=
0
;
i
<
_nblocks
;
++
i
)
block
[
i
].
set
(
m
,
this
->
p
+
(
i
*
m
));
// and the vector is usable
initialized
=
true
;
}
//! copy constructor, has copy semantics
VariableBlockVector
(
const
VariableBlockVector
&
a
)
VariableBlockVector
(
const
VariableBlockVector
&
a
)
:
block
(
a
.
block
),
storage_
(
a
.
storage_
)
{
// allocate the big array in the base class
this
->
n
=
a
.
n
;
if
(
this
->
n
>
0
)
{
// allocate and construct objects
this
->
p
=
allocator_
.
allocate
(
this
->
n
);
new
(
this
->
p
)
B
[
this
->
n
];
syncBaseArray
();
// copy data
for
(
size_type
i
=
0
;
i
<
this
->
n
;
i
++
)
this
->
p
[
i
]
=
a
.
p
[
i
];
}
else
{
this
->
n
=
0
;
this
->
p
=
nullptr
;
}
// we can allocate the windows now
nblocks
=
a
.
nblocks
;
if
(
nblocks
>
0
)
{
// alloc
block
=
windowAllocator_
.
allocate
(
nblocks
);
new
(
block
)
window_type
[
nblocks
];
// and we must set the windows
block
[
0
].
set
(
a
.
block
[
0
].
getsize
(),
this
->
p
);
// first block
for
(
size_type
i
=
1
;
i
<
nblocks
;
++
i
)
// and the rest
block
[
i
].
set
(
a
.
block
[
i
].
getsize
(),
block
[
i
-
1
].
getptr
()
+
block
[
i
-
1
].
getsize
());
}
else
{
nblocks
=
0
;
block
=
nullptr
;
// and we must set the windows
if
(
block
.
size
()
>
0
)
{
block
[
0
].
set
(
block
[
0
].
getsize
(),
this
->
p
);
// first block
for
(
size_type
i
=
1
;
i
<
block
.
size
();
++
i
)
// and the rest
block
[
i
].
set
(
block
[
i
].
getsize
(),
block
[
i
-
1
].
getptr
()
+
block
[
i
-
1
].
getsize
());
}
// and we have a usable vector
initialized
=
true
;
initialized
=
a
.
initialized
;
}
//! free dynamic memory
~
VariableBlockVector
()
{
if
(
this
->
n
>
0
)
{
size_type
i
=
this
->
n
;
while
(
i
)
this
->
p
[
--
i
].
~
B
();
allocator_
.
deallocate
(
this
->
p
,
this
->
n
);
}
if
(
nblocks
>
0
)
{
size_type
i
=
nblocks
;
while
(
i
)
block
[
--
i
].
~
window_type
();
windowAllocator_
.
deallocate
(
block
,
nblocks
);
}
}
~
VariableBlockVector
()
=
default
;
//! same effect as constructor with same argument
void
resize
(
size_type
_nblocks
)
{
// deconstruct objects and deallocate memory if necessary
if
(
this
->
n
>
0
)
{
size_type
i
=
this
->
n
;
while
(
i
)
this
->
p
[
--
i
].
~
B
();
allocator_
.
deallocate
(
this
->
p
,
this
->
n
);
}
if
(
nblocks
>
0
)
{
size_type
i
=
nblocks
;
while
(
i
)
block
[
--
i
].
~
window_type
();
windowAllocator_
.
deallocate
(
block
,
nblocks
);
}
this
->
n
=
0
;
this
->
p
=
nullptr
;
storage_
.
clear
();
syncBaseArray
();
// we can allocate the windows now
nblocks
=
_nblocks
;
if
(
nblocks
>
0
)
{
block
=
windowAllocator_
.
allocate
(
nblocks
);
new
(
block
)
window_type
[
nblocks
];
}
else
{
nblocks
=
0
;
block
=
nullptr
;
}
block
.
resize
(
_nblocks
);
// and the vector not fully usable
initialized
=
false
;
...
...
@@ -264,50 +164,14 @@ namespace Dune {
//! same effect as constructor with same argument
void
resize
(
size_type
_nblocks
,
size_type
m
)
{
// deconstruct objects and deallocate memory if necessary
if
(
this
->
n
>
0
)
{
size_type
i
=
this
->
n
;
while
(
i
)
this
->
p
[
--
i
].
~
B
();
allocator_
.
deallocate
(
this
->
p
,
this
->
n
);
}
if
(
nblocks
>
0
)
{
size_type
i
=
nblocks
;
while
(
i
)
block
[
--
i
].
~
window_type
();
windowAllocator_
.
deallocate
(
block
,
nblocks
);
}
// and we can allocate the big array in the base class
this
->
n
=
_nblocks
*
m
;
if
(
this
->
n
>
0
)
{
this
->
p
=
allocator_
.
allocate
(
this
->
n
);
new
(
this
->
p
)
B
[
this
->
n
];
}
else
{
this
->
n
=
0
;
this
->
p
=
nullptr
;
}
// we can allocate the windows now
nblocks
=
_nblocks
;
if
(
nblocks
>
0
)
{
// allocate and construct objects
block
=
windowAllocator_
.
allocate
(
nblocks
);
new
(
block
)
window_type
[
nblocks
];
storage_
.
resize
(
_nblocks
*
m
);
block
.
resize
(
_nblocks
);
syncBaseArray
();
// set the windows into the big array
for
(
size_type
i
=
0
;
i
<
nblocks
;
++
i
)
block
[
i
].
set
(
m
,
this
->
p
+
(
i
*
m
));
}
else
{
nblocks
=
0
;
block
=
nullptr
;
}
// set the windows into the big array
for
(
size_type
i
=
0
;
i
<
block
.
size
();
++
i
)
block
[
i
].
set
(
m
,
this
->
p
+
(
i
*
m
));
// and the vector is usable
initialized
=
true
;
...
...
@@ -318,64 +182,22 @@ namespace Dune {
{
if
(
&
a
!=
this
)
// check if this and a are different objects
{
// reallocate arrays if necessary
// Note: still the block sizes may vary !
if
(
this
->
n
!=
a
.
n
||
nblocks
!=
a
.
nblocks
)
{
// deconstruct objects and deallocate memory if necessary
if
(
this
->
n
>
0
)
{
size_type
i
=
this
->
n
;
while
(
i
)
this
->
p
[
--
i
].
~
B
();
allocator_
.
deallocate
(
this
->
p
,
this
->
n
);
}
if
(
nblocks
>
0
)
{
size_type
i
=
nblocks
;
while
(
i
)
block
[
--
i
].
~
window_type
();
windowAllocator_
.
deallocate
(
block
,
nblocks
);
}
// allocate the big array in the base class
this
->
n
=
a
.
n
;
if
(
this
->
n
>
0
)
{
// allocate and construct objects
this
->
p
=
allocator_
.
allocate
(
this
->
n
);
new
(
this
->
p
)
B
[
this
->
n
];
}
else
{
this
->
n
=
0
;
this
->
p
=
nullptr
;
}
// we can allocate the windows now
nblocks
=
a
.
nblocks
;
if
(
nblocks
>
0
)
{
// alloc
block
=
windowAllocator_
.
allocate
(
nblocks
);
new
(
block
)
window_type
[
nblocks
];
}
else
{
nblocks
=
0
;
block
=
nullptr
;
}
}
storage_
=
a
.
storage_
;
syncBaseArray
();
block
.
resize
(
a
.
block
.
size
());
// copy block structure, might be different although
// sizes are the same !
if
(
n
block
s
>
0
)
if
(
block
.
size
()
>
0
)
{
block
[
0
].
set
(
a
.
block
[
0
].
getsize
(),
this
->
p
);
// first block
for
(
size_type
i
=
1
;
i
<
n
block
s
;
++
i
)
// and the rest
for
(
size_type
i
=
1
;
i
<
block
.
size
()
;
++
i
)
// and the rest
block
[
i
].
set
(
a
.
block
[
i
].
getsize
(),
block
[
i
-
1
].
getptr
()
+
block
[
i
-
1
].
getsize
());
}
// and
copy the data
for
(
size_type
i
=
0
;
i
<
this
->
n
;
i
++
)
this
->
p
[
i
]
=
a
.
p
[
i
]
;
// and
we have a usable vector
initialized
=
a
.
initialized
;
;
}
// and we have a usable vector
...
...
@@ -469,7 +291,7 @@ namespace Dune {
// 1. the current iterator was not created as enditerator
// 2. we're at the last block
// 3. the vector hasn't been initialized earlier
if
(
not
isEnd
&&
i
==
v
.
n
block
s
&&
not
v
.
initialized
)
if
(
not
isEnd
&&
i
==
v
.
block
.
size
()
&&
not
v
.
initialized
)
v
.
allocate
();
}
...
...
@@ -546,7 +368,7 @@ namespace Dune {
//! get create iterator pointing to one after the last block
CreateIterator
createend
()
{
return
CreateIterator
(
*
this
,
n
block
s
,
true
);
return
CreateIterator
(
*
this
,
block
.
size
()
,
true
);
}
...
...
@@ -558,7 +380,7 @@ namespace Dune {
window_type
&
operator
[]
(
size_type
i
)
{
#ifdef DUNE_ISTL_WITH_CHECKING
if
(
i
>=
n
block
s
)
DUNE_THROW
(
ISTLError
,
"index out of range"
);
if
(
i
>=
block
.
size
()
)
DUNE_THROW
(
ISTLError
,
"index out of range"
);
#endif
return
block
[
i
];
}
...
...
@@ -567,113 +389,44 @@ namespace Dune {
const
window_type
&
operator
[]
(
size_type
i
)
const
{
#ifdef DUNE_ISTL_WITH_CHECKING
if
(
i
<
0
||
i
>=
n
block
s
)
DUNE_THROW
(
ISTLError
,
"index out of range"
);
if
(
i
<
0
||
i
>=
block
.
size
()
)
DUNE_THROW
(
ISTLError
,
"index out of range"
);
#endif
return
block
[
i
];
}
//! Iterator class for sequential access
template
<
class
T
,
class
R
>
class
RealIterator
:
public
RandomAccessIteratorFacade
<
RealIterator
<
T
,
R
>
,
T
,
R
>
{
public:
//! constructor, no arguments
RealIterator
()
{
p
=
nullptr
;
i
=
0
;
}
//! constructor
RealIterator
(
window_type
*
_p
,
size_type
_i
)
:
p
(
_p
),
i
(
_i
)
{}
//! prefix increment
void
increment
()
{
++
i
;
}
//! prefix decrement
void
decrement
()
{
--
i
;
}
//! equality
bool
equals
(
const
RealIterator
&
it
)
const
{
return
(
p
+
i
)
==
(
it
.
p
+
it
.
i
);
}
//! dereferencing
window_type
&
dereference
()
const
{
return
p
[
i
];
}
void
advance
(
std
::
ptrdiff_t
d
)
{
i
+=
d
;
}
std
::
ptrdiff_t
distanceTo
(
const
RealIterator
&
o
)
const
{
return
o
.
i
-
i
;
}
// Needed for operator[] of the iterator
window_type
&
elementAt
(
std
::
ptrdiff_t
offset
)
const
{
return
p
[
i
+
offset
];
}
/** \brief Return the index of the entry this iterator is pointing to */
size_type
index
()
const
{
return
i
;
}
private
:
window_type
*
p
;
size_type
i
;
};
using
Iterator
=
RealIterator
<
value_type
,
window_type
&>
;
using
Iterator
=
typename
VectorWindows
::
iterator
;
//! begin Iterator
Iterator
begin
()
{
return
Iterator
(
block
,
0
);
return
block
.
begin
(
);
}
//! end Iterator
Iterator
end
()
{
return
Iterator
(
block
,
nblocks
);
return
block
.
end
(
);
}
//! @returns an iterator that is positioned before
//! the end iterator of the vector, i.e. at the last entry.
Iterator
beforeEnd
()
{
return
Iterator
(
block
,
nblocks
-
1
);
return
--
block
.
end
(
);
}
//! @returns an iterator that is positioned before
//! the first entry of the vector.
Iterator
beforeBegin
()
const
{
return
Iterator
(
block
,
-
1
);
return
--
block
.
begin
(
);
}
/** \brief Export the iterator type using std naming rules */
using
iterator
=
Iterator
;
/** \brief Const iterator */
using
ConstIterator
=
RealIterator
<
const
value_type
,
const
window_type
&>
;
using
ConstIterator
=
typename
VectorWindows
::
const_iterator
;
/** \brief Export the const iterator type using std naming rules */
using
const_iterator
=
ConstIterator
;
...
...
@@ -681,38 +434,42 @@ namespace Dune {
//! begin ConstIterator
ConstIterator
begin
()
const
{
return
ConstIterator
(
block
,
0
);
return
block
.
begin
(
);
}
//! end ConstIterator
ConstIterator
end
()
const
{
return
ConstIterator
(
block
,
nblocks
);
return
block
.
end
(
);
}
//! @returns an iterator that is positioned before
//! the end iterator of the vector. i.e. at the last element.
ConstIterator
beforeEnd
()
const
{
return
ConstIterator
(
block
,
nblocks
-
1
);
return
--
block
.
end
(
);
}
//! end ConstIterator
ConstIterator
rend
()
const
{
return
ConstIterator
(
block
,
-
1
);
return
block
.
rend
(
);
}
//! random access returning iterator (end if not contained)
Iterator
find
(
size_type
i
)
{
return
Iterator
(
block
,
std
::
min
(
i
,
nblocks
));
auto
tmp
=
block
.
begin
();
tmp
+=
std
::
min
(
i
,
block
.
size
());
return
tmp
;
}
//! random access returning iterator (end if not contained)
ConstIterator
find
(
size_type
i
)
const
{
return
ConstIterator
(
block
,
std
::
min
(
i
,
nblocks
));
auto
tmp
=
block
.
begin
();
tmp
+=
std
::
min
(
i
,
block
.
size
());
return
tmp
;
}
//===== sizes
...
...
@@ -720,7 +477,7 @@ namespace Dune {
//! number of blocks in the vector (are of variable size here)
size_type
N
()
const
{
return
n
block
s
;
return
block
.
size
()
;
}
/** Number of blocks in the vector
...
...
@@ -729,7 +486,7 @@ namespace Dune {
*/
size_type
size
()
const
{
return
n
block
s
;
return
block
.
size
()
;
}
...
...
@@ -740,39 +497,31 @@ namespace Dune {
DUNE_THROW
(
ISTLError
,
"Attempt to re-allocate already initialized VariableBlockVector"
);
// calculate space needed:
this
->
n
=
0
;
for
(
size_type
i
=
0
;
i
<
nblocks
;
i
++
)
{
this
->
n
+=
block
[
i
].
size
();
}
size_type
storageNeeded
=
0
;
for
(
size_type
i
=
0
;
i
<
block
.
size
();
i
++
)
storageNeeded
+=
block
[
i
].
size
();
// now we can allocate the big array in the base class of v
if
(
this
->
n
>
0
)
{
// allocate and construct objects
this
->
p
=
allocator_
.
allocate
(
this
->
n
);
new
(
this
->
p
)
B
[
this
->
n
];
}
else
{
this
->
p
=
nullptr
;
}
storage_
.
resize
(
storageNeeded
);
syncBaseArray
();
// and we set the window pointers
this
->
block
[
0
].
setptr
(
this
->
p
);
// pointer to first block
for
(
size_type
j
=
1
;
j
<
n
block
s
;
++
j
)
// and the rest
block
[
0
].
setptr
(
this
->
p
);
// pointer to first block
for
(
size_type
j
=
1
;
j
<
block
.
size
()
;
++
j
)
// and the rest
block
[
j
].
setptr
(
block
[
j
-
1
].
getptr
()
+
block
[
j
-
1
].
getsize
());
// and the vector is ready
this
->
initialized
=
true
;
}
size_type
nblocks
;
// number of blocks in vector
window_type
*
block
;
// array of blocks pointing to the array in the base class
bool
initialized
;
// true if vector has been initialized
A
allocator_
;
void
syncBaseArray
()
noexcept
{
this
->
p
=
storage_
.
data
();
this
->
n
=
storage_
.
size
();
}
typename
std
::
allocator_traits
<
A
>::
template
rebind_alloc
<
window_type
>
windowAllocator_
;
VectorWindows
block
;
// vector of blocks pointing to the array in the base class
std
::
vector
<
B
,
A
>
storage_
;
bool
initialized
=
false
;
// true if vector has been initialized
};
/** @addtogroup DenseMatVec
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment