Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
amdis
amdis-core
Commits
5d6a1f99
Commit
5d6a1f99
authored
Oct 21, 2019
by
Praetorius, Simon
Browse files
Rewriting adaptive grid
parent
c03faa46
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
5d6a1f99
...
@@ -26,20 +26,35 @@ dune-2.6 ubuntu-18.04 clang-6-17:
...
@@ -26,20 +26,35 @@ dune-2.6 ubuntu-18.04 clang-6-17:
-
dunecontrol --current make -j4 examples
-
dunecontrol --current make -j4 examples
dune-git debian-10 gcc-8-17
:
.dune-git
:
image
:
registry.dune-project.org/docker/ci/dune:git-debian-10-gcc-8-17
before_script
:
-
. /duneci/bin/duneci-init-job
-
duneci-install-module https://gitlab.dune-project.org/core/dune-common.git
-
duneci-install-module https://gitlab.dune-project.org/core/dune-geometry.git
-
duneci-install-module https://gitlab.dune-project.org/core/dune-localfunctions.git
-
duneci-install-module https://gitlab.dune-project.org/staging/dune-uggrid.git
-
duneci-install-module https://gitlab.dune-project.org/core/dune-grid.git
-
duneci-install-module https://gitlab.dune-project.org/core/dune-istl.git
-
duneci-install-module https://gitlab.dune-project.org/staging/dune-typetree.git
-
duneci-install-module https://gitlab.dune-project.org/staging/dune-functions.git
script
:
script
:
-
duneci-standard-test
-
duneci-standard-test
-
dunecontrol --current make -j4 examples
-
dunecontrol --current make -j4 examples
dune-git debian-10 gcc-8-17
:
extends
:
.dune-git
image
:
registry.dune-project.org/docker/ci/debian:10
variables
:
DUNECI_TOOLCHAIN
:
gcc-8-17
dune-git debian-9 gcc-6-14
:
dune-git debian-9 gcc-6-14
:
image
:
registry.dune-project.org/docker/ci/dune:git-debian-9-gcc-6-14
extends
:
.dune-git
script
:
image
:
registry.dune-project.org/docker/ci/debian:9
-
duneci-standard-t
es
t
variabl
es
:
-
dunecontrol --current make -j4 examples
DUNECI_TOOLCHAIN
:
gcc-6-14
dune-git ubuntu-18.04 clang-6-17
:
dune-git ubuntu-18.04 clang-6-17
:
image
:
registry.dune-project.org/docker/ci/dune:git-ubuntu-18.04-clang-6-17
extends
:
.dune-git
script
:
image
:
registry.dune-project.org/docker/ci/ubuntu:18.04
-
duneci-standard-t
es
t
variabl
es
:
-
dunecontrol --current make -j4 examples
DUNECI_TOOLCHAIN
:
clang-6-17
src/amdis/AdaptiveGrid.hpp
View file @
5d6a1f99
This diff is collapsed.
Click to expand it.
src/amdis/DOFVector.hpp
View file @
5d6a1f99
...
@@ -65,7 +65,7 @@ namespace AMDiS
...
@@ -65,7 +65,7 @@ namespace AMDiS
public:
public:
/// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
/// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
DOFVector
(
std
::
shared_ptr
<
GB
>
basis
,
DOFVector
(
std
::
shared_ptr
<
GB
>
const
&
basis
,
DataTransferOperation
op
=
DataTransferOperation
::
INTERPOLATE
)
DataTransferOperation
op
=
DataTransferOperation
::
INTERPOLATE
)
:
Super
(
basis
)
:
Super
(
basis
)
,
Obs
(
basis
)
,
Obs
(
basis
)
...
...
src/amdis/MeshCreator.hpp
View file @
5d6a1f99
...
@@ -43,10 +43,11 @@ namespace AMDiS
...
@@ -43,10 +43,11 @@ namespace AMDiS
enum
{
dimworld
=
Grid
::
dimensionworld
};
enum
{
dimworld
=
Grid
::
dimensionworld
};
using
ctype
=
typename
Grid
::
ctype
;
using
ctype
=
typename
Grid
::
ctype
;
using
HostGrid
=
typename
AdaptiveGrid_t
<
Grid
>::
HostGrid
;
/// Construct a new MeshCreator
/// Construct a new MeshCreator
/**
/**
* \param name The name of the mesh used in the init
i
file
* \param name The name of the mesh used in the initfile
**/
**/
MeshCreator
(
std
::
string
const
&
name
)
MeshCreator
(
std
::
string
const
&
name
)
:
name_
(
name
)
:
name_
(
name
)
...
@@ -64,11 +65,11 @@ namespace AMDiS
...
@@ -64,11 +65,11 @@ namespace AMDiS
*
*
* Otherwise tries to create a grid depending on the grid type.
* Otherwise tries to create a grid depending on the grid type.
**/
**/
std
::
shared_ptr
<
AdaptiveGrid
<
Grid
>
>
create
()
const
std
::
shared_ptr
<
Grid
>
create
()
const
{
{
auto
filename
=
Parameters
::
get
<
std
::
string
>
(
name_
+
"->macro file name"
);
auto
filename
=
Parameters
::
get
<
std
::
string
>
(
name_
+
"->macro file name"
);
auto
structured
=
Parameters
::
get
<
std
::
string
>
(
name_
+
"->structured"
);
auto
structured
=
Parameters
::
get
<
std
::
string
>
(
name_
+
"->structured"
);
std
::
shared
_ptr
<
Grid
>
gridPtr
;
std
::
unique
_ptr
<
Host
Grid
>
gridPtr
;
if
(
filename
)
{
if
(
filename
)
{
// read a macro file
// read a macro file
gridPtr
=
create_unstructured_grid
(
filename
.
value
());
gridPtr
=
create_unstructured_grid
(
filename
.
value
());
...
@@ -83,26 +84,26 @@ namespace AMDiS
...
@@ -83,26 +84,26 @@ namespace AMDiS
}
}
}
else
{
}
else
{
// decide by inspecting the grid type how to create the grid
// decide by inspecting the grid type how to create the grid
gridPtr
=
create_by_gridtype
<
Grid
>
(
Dune
::
PriorityTag
<
42
>
{});
gridPtr
=
create_by_gridtype
<
Host
Grid
>
(
Dune
::
PriorityTag
<
42
>
{});
}
}
return
AdaptiveGrid
<
Grid
>::
instanc
e
(
gridPtr
);
return
construct
(
std
::
mov
e
(
gridPtr
)
)
;
}
}
/// Create a structured cube grid
/// Create a structured cube grid
std
::
unique_ptr
<
Grid
>
create_cube_grid
()
const
std
::
unique_ptr
<
Host
Grid
>
create_cube_grid
()
const
{
{
return
create_structured_grid
([](
auto
&&
lower
,
auto
&&
upper
,
auto
&&
numCells
)
return
create_structured_grid
([](
auto
&&
lower
,
auto
&&
upper
,
auto
&&
numCells
)
{
{
return
Dune
::
StructuredGridFactory
<
Grid
>::
createCubeGrid
(
lower
,
upper
,
numCells
);
return
Dune
::
StructuredGridFactory
<
Host
Grid
>::
createCubeGrid
(
lower
,
upper
,
numCells
);
});
});
}
}
/// Create a structured simplex grid
/// Create a structured simplex grid
std
::
unique_ptr
<
Grid
>
create_simplex_grid
()
const
std
::
unique_ptr
<
Host
Grid
>
create_simplex_grid
()
const
{
{
return
create_structured_grid
([](
auto
&&
lower
,
auto
&&
upper
,
auto
&&
numCells
)
return
create_structured_grid
([](
auto
&&
lower
,
auto
&&
upper
,
auto
&&
numCells
)
{
{
return
Dune
::
StructuredGridFactory
<
Grid
>::
createSimplexGrid
(
lower
,
upper
,
numCells
);
return
Dune
::
StructuredGridFactory
<
Host
Grid
>::
createSimplexGrid
(
lower
,
upper
,
numCells
);
});
});
}
}
...
@@ -119,9 +120,20 @@ namespace AMDiS
...
@@ -119,9 +120,20 @@ namespace AMDiS
}
}
private:
private:
static
std
::
shared_ptr
<
Grid
>
construct
(
std
::
unique_ptr
<
Grid
>
hostGrid
)
{
return
std
::
move
(
hostGrid
);
}
template
<
class
HG
>
static
std
::
shared_ptr
<
Grid
>
construct
(
std
::
unique_ptr
<
HG
>
hostGrid
)
{
return
std
::
make_shared
<
Grid
>
(
std
::
move
(
hostGrid
));
}
// use the structured grid factory to create the grid
// use the structured grid factory to create the grid
template
<
class
Size
=
unsigned
int
,
class
Factory
>
template
<
class
Size
=
unsigned
int
,
class
Factory
>
std
::
unique_ptr
<
Grid
>
create_structured_grid
(
Factory
factory
)
const
std
::
unique_ptr
<
Host
Grid
>
create_structured_grid
(
Factory
factory
)
const
{
{
// Lower left corner of the domain
// Lower left corner of the domain
Dune
::
FieldVector
<
ctype
,
int
(
dimworld
)
>
lower
(
0
);
Dune
::
FieldVector
<
ctype
,
int
(
dimworld
)
>
lower
(
0
);
...
@@ -137,16 +149,16 @@ namespace AMDiS
...
@@ -137,16 +149,16 @@ namespace AMDiS
}
}
// read a filename from `[meshName]->macro file name` and determine from the extension the fileformat
// read a filename from `[meshName]->macro file name` and determine from the extension the fileformat
std
::
unique_ptr
<
Grid
>
create_unstructured_grid
(
std
::
string
const
&
filename
)
const
std
::
unique_ptr
<
Host
Grid
>
create_unstructured_grid
(
std
::
string
const
&
filename
)
const
{
{
filesystem
::
path
fn
(
filename
);
filesystem
::
path
fn
(
filename
);
auto
ext
=
fn
.
extension
();
auto
ext
=
fn
.
extension
();
if
(
ext
==
".msh"
)
{
if
(
ext
==
".msh"
)
{
return
read_gmsh_file
<
Grid
>
(
filename
,
Dune
::
PriorityTag
<
42
>
{});
return
read_gmsh_file
<
Host
Grid
>
(
filename
,
Dune
::
PriorityTag
<
42
>
{});
}
}
else
if
(
ext
==
".1d"
||
ext
==
".2d"
||
ext
==
".3d"
||
ext
==
".amc"
)
{
else
if
(
ext
==
".1d"
||
ext
==
".2d"
||
ext
==
".3d"
||
ext
==
".amc"
)
{
return
read_alberta_file
<
Grid
>
(
filename
,
Dune
::
PriorityTag
<
42
>
{});
return
read_alberta_file
<
Host
Grid
>
(
filename
,
Dune
::
PriorityTag
<
42
>
{});
}
}
else
{
else
{
error_exit
(
"Cannot read grid file. Unknown file extension."
);
error_exit
(
"Cannot read grid file. Unknown file extension."
);
...
@@ -160,7 +172,7 @@ namespace AMDiS
...
@@ -160,7 +172,7 @@ namespace AMDiS
std
::
declval
<
std
::
shared_ptr
<
Dune
::
BoundarySegment
<
GridType
::
dimension
,
GridType
::
dimensionworld
>
>>
())
);
std
::
declval
<
std
::
shared_ptr
<
Dune
::
BoundarySegment
<
GridType
::
dimension
,
GridType
::
dimensionworld
>
>>
())
);
// use GmshReader if GridFactory supports insertBoundarySegments
// use GmshReader if GridFactory supports insertBoundarySegments
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
REQUIRES
(
Dune
::
Std
::
is_detected
<
SupportsGmshReader
,
GridType
>
::
value
)
>
REQUIRES
(
Dune
::
Std
::
is_detected
<
SupportsGmshReader
,
GridType
>
::
value
)
>
std
::
unique_ptr
<
GridType
>
read_gmsh_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
1
>
)
const
std
::
unique_ptr
<
GridType
>
read_gmsh_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
1
>
)
const
{
{
...
@@ -169,7 +181,7 @@ namespace AMDiS
...
@@ -169,7 +181,7 @@ namespace AMDiS
}
}
// fallback if GmshReader cannot be used
// fallback if GmshReader cannot be used
template
<
class
GridType
=
Grid
>
template
<
class
GridType
=
Host
Grid
>
std
::
unique_ptr
<
GridType
>
read_gmsh_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
0
>
)
const
std
::
unique_ptr
<
GridType
>
read_gmsh_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
0
>
)
const
{
{
error_exit
(
"Gmsh reader not supported for this grid type!"
);
error_exit
(
"Gmsh reader not supported for this grid type!"
);
...
@@ -183,7 +195,7 @@ namespace AMDiS
...
@@ -183,7 +195,7 @@ namespace AMDiS
using
IsAlbertaGrid
=
decltype
(
std
::
declval
<
GridType
>
().
alberta2dune
(
0
,
0
));
using
IsAlbertaGrid
=
decltype
(
std
::
declval
<
GridType
>
().
alberta2dune
(
0
,
0
));
// construct the albertagrid directly from a filename
// construct the albertagrid directly from a filename
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
REQUIRES
(
GridType
::
dimensionworld
==
DIM_OF_WORLD
),
REQUIRES
(
GridType
::
dimensionworld
==
DIM_OF_WORLD
),
REQUIRES
(
Dune
::
Std
::
is_detected
<
IsAlbertaGrid
,
GridType
>
::
value
)
>
REQUIRES
(
Dune
::
Std
::
is_detected
<
IsAlbertaGrid
,
GridType
>
::
value
)
>
std
::
unique_ptr
<
GridType
>
read_alberta_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
3
>
)
const
std
::
unique_ptr
<
GridType
>
read_alberta_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
3
>
)
const
...
@@ -192,7 +204,7 @@ namespace AMDiS
...
@@ -192,7 +204,7 @@ namespace AMDiS
}
}
// use a gridfactory and the generic AlbertaReader
// use a gridfactory and the generic AlbertaReader
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
REQUIRES
(
GridType
::
dimensionworld
==
DIM_OF_WORLD
)>
REQUIRES
(
GridType
::
dimensionworld
==
DIM_OF_WORLD
)>
std
::
unique_ptr
<
GridType
>
read_alberta_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
2
>
)
const
std
::
unique_ptr
<
GridType
>
read_alberta_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
2
>
)
const
{
{
...
@@ -205,7 +217,7 @@ namespace AMDiS
...
@@ -205,7 +217,7 @@ namespace AMDiS
}
}
// error if WORLDDIM not the same as Grid::dimensionworld
// error if WORLDDIM not the same as Grid::dimensionworld
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
REQUIRES
(
GridType
::
dimensionworld
!=
DIM_OF_WORLD
)>
REQUIRES
(
GridType
::
dimensionworld
!=
DIM_OF_WORLD
)>
std
::
unique_ptr
<
GridType
>
read_alberta_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
1
>
)
const
std
::
unique_ptr
<
GridType
>
read_alberta_file
(
std
::
string
const
&
filename
,
Dune
::
PriorityTag
<
1
>
)
const
{
{
...
@@ -225,19 +237,19 @@ namespace AMDiS
...
@@ -225,19 +237,19 @@ namespace AMDiS
#if HAVE_ALBERTA
#if HAVE_ALBERTA
// albertagrid -> simplex
// albertagrid -> simplex
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
REQUIRES
(
Dune
::
Std
::
is_detected
<
IsAlbertaGrid
,
GridType
>
::
value
)
>
REQUIRES
(
Dune
::
Std
::
is_detected
<
IsAlbertaGrid
,
GridType
>
::
value
)
>
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
3
>
)
const
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
3
>
)
const
{
{
return
create_structured_grid
([](
auto
&&
lower
,
auto
&&
upper
,
auto
&&
numCells
)
return
create_structured_grid
([](
auto
&&
lower
,
auto
&&
upper
,
auto
&&
numCells
)
{
{
return
MacroGridFactory
<
Grid
>::
createSimplexGrid
(
lower
,
upper
,
numCells
);
return
MacroGridFactory
<
Grid
Type
>::
createSimplexGrid
(
lower
,
upper
,
numCells
);
});
});
}
}
#endif
#endif
// yasp grid -> cube
// yasp grid -> cube
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
class
=
typename
GridType
::
YGrid
>
class
=
typename
GridType
::
YGrid
>
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
2
>
)
const
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
2
>
)
const
{
{
...
@@ -250,27 +262,27 @@ namespace AMDiS
...
@@ -250,27 +262,27 @@ namespace AMDiS
}
}
template
<
int
dim
,
class
ct
>
template
<
int
dim
,
class
ct
>
std
::
unique_ptr
<
Grid
>
create_yaspgrid
(
Types
<
Dune
::
YaspGrid
<
dim
,
Dune
::
EquidistantCoordinates
<
ct
,
dim
>>>
,
std
::
unique_ptr
<
Host
Grid
>
create_yaspgrid
(
Types
<
Dune
::
YaspGrid
<
dim
,
Dune
::
EquidistantCoordinates
<
ct
,
dim
>>>
,
int
overlap
,
std
::
bitset
<
dimension
>
const
&
per
)
const
int
overlap
,
std
::
bitset
<
dimension
>
const
&
per
)
const
{
{
return
create_structured_grid
<
int
>
([
&
](
auto
&&
/*lower*/
,
auto
&&
upper
,
std
::
array
<
int
,
dimension
>
const
&
numCells
)
return
create_structured_grid
<
int
>
([
&
](
auto
&&
/*lower*/
,
auto
&&
upper
,
std
::
array
<
int
,
dimension
>
const
&
numCells
)
{
{
return
std
::
make_unique
<
Grid
>
(
upper
,
numCells
,
per
,
overlap
);
return
std
::
make_unique
<
Host
Grid
>
(
upper
,
numCells
,
per
,
overlap
);
});
});
}
}
template
<
int
dim
,
class
ct
>
template
<
int
dim
,
class
ct
>
std
::
unique_ptr
<
Grid
>
create_yaspgrid
(
Types
<
Dune
::
YaspGrid
<
dim
,
Dune
::
EquidistantOffsetCoordinates
<
ct
,
dim
>>>
,
std
::
unique_ptr
<
Host
Grid
>
create_yaspgrid
(
Types
<
Dune
::
YaspGrid
<
dim
,
Dune
::
EquidistantOffsetCoordinates
<
ct
,
dim
>>>
,
int
overlap
,
std
::
bitset
<
dimension
>
const
&
per
)
const
int
overlap
,
std
::
bitset
<
dimension
>
const
&
per
)
const
{
{
return
create_structured_grid
<
int
>
([
&
](
auto
&&
lower
,
auto
&&
upper
,
std
::
array
<
int
,
dimension
>
const
&
numCells
)
return
create_structured_grid
<
int
>
([
&
](
auto
&&
lower
,
auto
&&
upper
,
std
::
array
<
int
,
dimension
>
const
&
numCells
)
{
{
return
std
::
make_unique
<
Grid
>
(
lower
,
upper
,
numCells
,
per
,
overlap
);
return
std
::
make_unique
<
Host
Grid
>
(
lower
,
upper
,
numCells
,
per
,
overlap
);
});
});
}
}
template
<
int
dim
,
class
ct
>
template
<
int
dim
,
class
ct
>
std
::
unique_ptr
<
Grid
>
create_yaspgrid
(
Types
<
Dune
::
YaspGrid
<
dim
,
Dune
::
TensorProductCoordinates
<
ct
,
dim
>>>
,
std
::
unique_ptr
<
Host
Grid
>
create_yaspgrid
(
Types
<
Dune
::
YaspGrid
<
dim
,
Dune
::
TensorProductCoordinates
<
ct
,
dim
>>>
,
int
overlap
,
std
::
bitset
<
dimension
>
const
&
per
)
const
int
overlap
,
std
::
bitset
<
dimension
>
const
&
per
)
const
{
{
error_exit
(
"MeshCreator cannot create YaspGrid with TensorProductCoordinates."
);
error_exit
(
"MeshCreator cannot create YaspGrid with TensorProductCoordinates."
);
...
@@ -280,7 +292,7 @@ namespace AMDiS
...
@@ -280,7 +292,7 @@ namespace AMDiS
#if HAVE_DUNE_SPGRID
#if HAVE_DUNE_SPGRID
// spgrid -> cube
// spgrid -> cube
template
<
class
GridType
=
Grid
,
template
<
class
GridType
=
Host
Grid
,
class
=
typename
GridType
::
ReferenceCube
,
class
=
typename
GridType
::
ReferenceCube
,
class
=
typename
GridType
::
MultiIndex
>
class
=
typename
GridType
::
MultiIndex
>
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
1
>
)
const
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
1
>
)
const
...
@@ -294,7 +306,7 @@ namespace AMDiS
...
@@ -294,7 +306,7 @@ namespace AMDiS
#endif
#endif
// final fallback
// final fallback
template
<
class
GridType
=
Grid
>
template
<
class
GridType
=
Host
Grid
>
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
0
>
)
const
std
::
unique_ptr
<
GridType
>
create_by_gridtype
(
Dune
::
PriorityTag
<
0
>
)
const
{
{
error_exit
(
"Don't know how to create the grid."
);
error_exit
(
"Don't know how to create the grid."
);
...
...
src/amdis/Observer.hpp
View file @
5d6a1f99
...
@@ -5,6 +5,8 @@
...
@@ -5,6 +5,8 @@
#include
<memory>
#include
<memory>
#include
<type_traits>
#include
<type_traits>
#include
<dune/common/typeutilities.hh>
#include
<amdis/common/ConceptsBase.hpp>
#include
<amdis/common/ConceptsBase.hpp>
#include
<amdis/Output.hpp>
#include
<amdis/Output.hpp>
...
@@ -12,135 +14,128 @@ namespace AMDiS
...
@@ -12,135 +14,128 @@ namespace AMDiS
{
{
namespace
Impl
namespace
Impl
{
{
//
F
orward declaration
//
f
orward declaration
template
<
class
Event
>
template
<
class
Event
>
class
Signal
Interface
;
class
Observer
Interface
;
template
<
class
Event
>
template
<
class
Event
>
class
ObserverInterfac
e
class
SignalBas
e
{
{
public:
public:
virtual
~
ObserverInterface
()
=
default
;
/// Attaches an observer to this class. This method will be called by all observers with
/// with themselves as argument.
/// Attach the observer to a subject. It will then receive notifications from the subject when
void
attachObserver
(
ObserverInterface
<
Event
>*
o
)
const
/// an event of type Event it triggered.
void
attach
(
std
::
shared_ptr
<
SignalInterface
<
Event
>>
const
&
subject
)
{
{
subject
->
attachObserver
(
this
);
observers_
.
push_back
(
o
);
}
}
/// Detach
the
observer
from the subject. It will then no longer receive notifications. This
/// Detach
es an
observer
to this class. This method will be called by all observers with
///
must be called before
the
ob
se
r
ve
r is deleted
.
///
with
the
m
se
l
ve
s as argument
.
void
detach
(
std
::
shared_ptr
<
Signal
Interface
<
Event
>
>
const
&
subject
)
void
detach
Observer
(
Observer
Interface
<
Event
>
*
o
)
const
{
{
subject
->
detachObserver
(
this
);
auto
it
=
std
::
find
(
observers_
.
begin
(),
observers_
.
end
(),
o
);
if
(
it
!=
observers_
.
end
())
observers_
.
erase
(
it
);
}
}
///
This method will be called by the subject when triggering the event.
///
Notify all observers that have called attachObserver but have not called detachObserver
v
irtual
void
update
(
Event
const
&
)
v
oid
notify
(
Event
const
&
e
)
const
{
{
error_exit
(
"Method must be overridden by derived class"
);
for
(
ObserverInterface
<
Event
>*
o
:
observers_
)
o
->
update
(
e
);
}
}
};
template
<
class
Event
>
class
SignalInterface
{
public:
virtual
~
SignalInterface
()
=
default
;
/// Attaches an observer to this class. This method will be called by all observers with
private:
/// with themselves as argument.
/// List of observers that need to be notified in case of an event
virtual
void
attachObserver
(
ObserverInterface
<
Event
>*
)
=
0
;
// NOTE: this list is mutable, since the notification list itself is not part
// of the internal state of the object signaling the event.
/// Detaches an observer to this class. This method will be called by all observers with
mutable
std
::
list
<
ObserverInterface
<
Event
>*>
observers_
;
/// with themselves as argument.
virtual
void
detachObserver
(
ObserverInterface
<
Event
>*
)
=
0
;
/// Notify all observers that have called attachObserver but have not called detachObserver
virtual
void
notify
(
Event
const
&
)
const
=
0
;
};
};
template
<
class
Event
>
template
<
class
Event
>
class
SignalsImpl
class
ObserverInterface
:
virtual
public
SignalInterface
<
Event
>
{
{
public:
public:
virtual
~
SignalsImpl
()
=
default
;
virtual
~
ObserverInterface
()
=
default
;
void
attachObserver
(
ObserverInterface
<
Event
>*
o
)
override
/// Attach the observer to a subject. It will then receive notifications from the subject when
/// an event of type Event it triggered.
void
attach
(
std
::
shared_ptr
<
SignalBase
<
Event
>
const
>
const
&
subject
)
{
{
observers_
.
push_back
(
o
);
if
(
bool
(
subject
))
subject
->
attachObserver
(
this
);
}
}
void
detachObserver
(
ObserverInterface
<
Event
>*
o
)
override
/// Detach the observer from the subject. It will then no longer receive notifications. This
/// must be called before the observer is deleted.
void
detach
(
std
::
shared_ptr
<
SignalBase
<
Event
>
const
>
const
&
subject
)
{
{
auto
it
=
std
::
find
(
observers_
.
begin
(),
observers_
.
end
(),
o
);
if
(
bool
(
subject
))
if
(
it
!=
observers_
.
end
())
subject
->
detachObserver
(
this
);
observers_
.
erase
(
it
);
}
}
void
notify
(
Event
const
&
e
)
const
override
/// This method will be called by the subject when triggering the event.
virtual
void
update
(
Event
const
&
)
{
{
for
(
ObserverInterface
<
Event
>*
o
:
observers_
)
error_exit
(
"Method must be overridden by derived class"
);
o
->
update
(
e
);
}
}
private:
std
::
list
<
ObserverInterface
<
Event
>*>
observers_
;
};
};
template
<
class
Event
>
class
SignalsDummy
:
virtual
public
SignalInterface
<
Event
>
{
public:
virtual
~
SignalsDummy
()
=
default
;
void
attachObserver
(
ObserverInterface
<
Event
>*
o
)
override
{}
void
detachObserver
(
ObserverInterface
<
Event
>*
o
)
override
{}
void
notify
(
Event
const
&
e
)
const
override
{}
};
template
<
class
Event
>
template
<
class
Event
>
class
Observer
Impl
class
Observer
Base
:
virtual
public
ObserverInterface
<
Event
>
:
virtual
public
ObserverInterface
<
Event
>
{
{
using
Self
=
Observer
Impl
;
using
Self
=
Observer
Base
;
ObserverImpl
()
private:
:
subject_
(
std
::
make_shared
<
SignalsDummy
<
Event
>>
())
ObserverBase
()
=
default
;
{}
public:
// use subject if Event is handled directly
ObserverImpl
(
std
::
shared_ptr
<
SignalInterface
<
Event
>>
subject
)
template
<
class
S
,
REQUIRES
(
std
::
is_base_of
<
SignalBase
<
Event
>,
S
>::
value
)
>
ObserverBase
(
std
::
shared_ptr
<
S
const
>
subject
,
Dune
::
PriorityTag
<
2
>
)
:
subject_
(
std
::
move
(
subject
))
:
subject_
(
std
::
move
(
subject
))
{
{
this
->
attach
(
subject_
);
this
->
attach
(
subject_
);
}
}
// Get next subject in hierarchy if Event is not handled
// get next subject in hierarchy if Event is not handled
template
<
class
Subject
,
template
<
class
Observer
,
REQUIRES
(
!
std
::
is_convertible
<
std
::
shared_ptr
<
Subject
>,
std
::
shared_ptr
<
SignalInterface
<
Event
>>>::
value
)
>
class
=
void_t
<
decltype
(
std
::
declval
<
Observer
>().
subject_
)
>
>
ObserverImpl
(
std
::
shared_ptr
<
Subject
>
subject
)
ObserverBase
(
std
::
shared_ptr
<
Observer
const
>
const
&
o
,
Dune
::
PriorityTag
<
1
>
)
:
Self
(
subject
->
getSubject
())
:
ObserverBase
(
o
->
subject_
)
{}
// non-observable type
template
<
class
T
>
ObserverBase
(
std
::
shared_ptr
<
T
const
>
const
&
other
,
Dune
::
PriorityTag
<
0
>
)
{
/* fallback implementation */
}
public: