Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F71225827
component_libmultiscale.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Jul 10, 10:10
Size
10 KB
Mime Type
text/x-c
Expires
Fri, Jul 12, 10:10 (2 d)
Engine
blob
Format
Raw Data
Handle
18923208
Attached To
rLIBMULTISCALE LibMultiScale
component_libmultiscale.cc
View Options
/* -------------------------------------------------------------------------- */
#include "component_libmultiscale.hh"
#include "comm_group.hh"
#include "container_array.hh"
#include "lm_communicator.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
#define secure(...) secure_call([&]() { __VA_ARGS__; });
/* --------------------------------------------------------------------- */
// OutputContainer
/* --------------------------------------------------------------------- */
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
OutputContainer
&
out
)
{
out
.
get
().
printself
(
os
);
return
os
;
}
OutputContainer
&
OutputContainer
::
operator
=
(
Component
&
v
)
{
AutoDispatch
::
ArgumentAny
::
operator
=
(
v
);
this
->
component
=
&
v
;
return
*
this
;
}
UInt
OutputContainer
::
evalRelease
()
const
{
UInt
release
=
this
->
get
().
getRelease
();
if
(
component
)
return
hash_releases
(
release
,
component
->
evalRelease
());
return
release
;
}
/* ---------------------------------------------------------------------- */
UInt
OutputContainer
::
getRelease
()
const
{
UInt
release
=
this
->
get
().
getRelease
();
if
(
component
)
return
hash_releases
(
release
,
component
->
getRelease
());
return
release
;
}
/* --------------------------------------------------------------------- */
// InputContainer
/* --------------------------------------------------------------------- */
InputContainer
&
InputContainer
::
operator
=
(
OutputContainer
&
v
)
{
output_reference
=
&
v
;
return
*
this
;
}
/* --------------------------------------------------------------------- */
InputContainer
&
InputContainer
::
operator
=
(
OutputContainer
&&
v
)
{
output_reference
=
std
::
make_shared
<
OutputContainer
>
(
std
::
forward
<
OutputContainer
>
(
v
));
return
*
this
;
}
OutputContainer
&
InputContainer
::
get
()
const
{
try
{
auto
*
ptr
=
std
::
any_cast
<
OutputContainer
*>
(
output_reference
);
return
*
ptr
;
}
catch
(
std
::
bad_any_cast
&
e
)
{
}
auto
ptr
=
std
::
any_cast
<
std
::
shared_ptr
<
OutputContainer
>>
(
output_reference
);
return
*
ptr
;
}
/* --------------------------------------------------------------------- */
OutputContainer
&
InputContainer
::
eval
()
const
{
OutputContainer
&
out
=
this
->
get
();
if
(
out
.
component
!=
nullptr
)
{
out
.
component
->
compute
();
}
return
out
;
}
/* --------------------------------------------------------------------- */
UInt
InputContainer
::
evalRelease
()
const
{
OutputContainer
&
out
=
this
->
get
();
return
out
.
evalRelease
();
}
/* --------------------------------------------------------------------- */
UInt
InputContainer
::
getRelease
()
const
{
OutputContainer
&
out
=
this
->
get
();
return
out
.
getRelease
();
}
/* -------------------------------------------------------------------------- */
// Component
/* -------------------------------------------------------------------------- */
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Component
&
comp
)
{
comp
.
printself
(
os
);
return
os
;
}
/* --------------------------------------------------------------------- */
Component
::
Component
()
:
calculated_once
(
false
)
{}
/* --------------------------------------------------------------------- */
InputContainer
&
Component
::
getInternalInput
(
const
std
::
string
&
requested_input
)
{
auto
&&
[
input
,
arg_cont_input
]
=
getContainer
(
requested_input
,
inputs
);
if
(
not
arg_cont_input
.
has_value
())
throw
UnconnectedInput
{
"For component '"
+
this
->
getID
()
+
"' input '"
+
input
+
"' is not connected"
};
return
arg_cont_input
;
}
/* --------------------------------------------------------------------- */
OutputContainer
&
Component
::
getInput
(
const
std
::
string
&
requested_input
)
{
return
this
->
getInternalInput
(
requested_input
).
eval
();
}
/* --------------------------------------------------------------------- */
OutputContainer
&
Component
::
getOutput
(
const
std
::
string
&
output_name
)
{
auto
&&
[
name
,
output
]
=
getContainer
(
output_name
,
outputs
);
return
output
;
}
/* --------------------------------------------------------------------- */
OutputContainer
&
Component
::
evalOutput
(
const
std
::
string
&
output_name
)
{
this
->
compute
();
return
getOutput
(
output_name
);
}
/* --------------------------------------------------------------------- */
auto
Component
::
evalOutputs
()
->
const
decltype
(
outputs
)
&
{
this
->
compute
();
return
outputs
;
}
/* --------------------------------------------------------------------- */
auto
Component
::
getOutputs
()
->
const
decltype
(
outputs
)
&
{
return
outputs
;
}
/* --------------------------------------------------------------------- */
void
Component
::
printself
(
std
::
ostream
&
os
)
const
{
for
(
auto
&
pair
:
this
->
inputs
)
{
os
<<
"input "
<<
pair
.
first
<<
":"
;
if
(
pair
.
second
.
has_value
())
os
<<
pair
.
second
.
get
()
<<
"
\n
"
;
else
os
<<
"not yet defined/computed
\n
"
;
}
for
(
auto
&
pair
:
this
->
outputs
)
{
os
<<
"output "
<<
pair
.
first
<<
":"
;
try
{
os
<<
pair
.
second
.
get
()
<<
"
\n
"
;
}
catch
(...)
{
os
<<
"not yet defined/computed
\n
"
;
}
}
}
/* --------------------------------------------------------------------- */
void
Component
::
connect
(
const
std
::
string
&
input
,
Component
&
comp
,
const
std
::
string
&
output
)
{
try
{
this
->
connect
(
input
,
comp
.
getOutput
(
output
));
}
catch
(
LibMultiScaleException
&
e
)
{
if
(
output
==
""
)
inputs
[
input
]
=
comp
;
else
throw
e
;
}
}
/* --------------------------------------------------------------------- */
OutputContainer
&
Component
::
createOutput
(
const
std
::
string
&
output
)
{
outputs
[
output
]
=
OutputContainer
(
*
this
,
output
);
return
outputs
[
output
];
}
/* --------------------------------------------------------------------- */
InputContainer
&
Component
::
createInput
(
const
std
::
string
&
input
)
{
inputs
[
input
]
=
InputContainer
();
return
inputs
[
input
];
}
/* --------------------------------------------------------------------- */
void
Component
::
removeInput
(
const
std
::
string
&
input
)
{
inputs
.
erase
(
input
);
}
/* --------------------------------------------------------------------- */
void
Component
::
compute
()
{
auto
secure_call
=
[
&
](
auto
&&
f
)
{
try
{
f
();
}
catch
(
LibMultiScaleException
&
e
)
{
LM_FATAL_RE
(
e
,
"compute of "
<<
this
->
getID
()
<<
" failed"
);
}
catch
(
std
::
exception
&
e
)
{
LM_FATAL
(
"compute of "
<<
this
->
getID
()
<<
" failed => "
<<
e
.
what
());
}
catch
(...)
{
LM_FATAL
(
"compute of "
<<
this
->
getID
()
<<
" failed => unknown exception was raised"
);
}
};
bool
need_recompute
=
this
->
evalDependencies
();
bool
amIinGroup
=
comm_group
==
nullptr
||
comm_group
->
amIinGroup
();
if
(
not
amIinGroup
)
{
throw
NotInCommGroup
{
"For component '"
+
this
->
getID
()
+
" I am not in the right group"
};
}
if
(
!
need_recompute
&&
calculated_once
)
return
;
// evalutate the inputs
secure
(
this
->
evalInputs
());
// get the context (comm_group, release) from inputs
secure
(
this
->
acquireInputsContext
());
// call the component code
secure
(
this
->
compute_make_call
());
// propagate the contexts from inputs to outputs
secure
(
this
->
acquireInputsContext
());
// sets the context to outputs
secure
(
this
->
propagateContextToOutputs
());
calculated_once
=
true
;
}
#undef secure
/* -------------------------------------------------------------------------- */
void
Component
::
evalInputs
()
{
for
(
auto
&&
[
name
,
inp
]
:
this
->
inputs
)
{
if
(
not
inp
.
has_value
())
LM_FATAL
(
"Component("
<<
this
->
getID
()
<<
"): input("
<<
name
<<
") was not created/computed/connected"
);
inp
.
eval
();
}
}
/* -------------------------------------------------------------------------- */
void
Component
::
acquireInputsContext
()
{
if
(
this
->
inputs
.
size
()
==
0
)
{
this
->
changeRelease
();
}
for
(
auto
&&
[
name
,
inp
]
:
this
->
inputs
)
{
if
(
not
inp
.
has_value
())
LM_FATAL
(
name
<<
": input was not created/computed/connected"
);
auto
&
connected_output
=
inp
.
get
();
if
(
connected_output
.
has_argument
())
this
->
acquireContext
(
connected_output
.
get
());
}
UInt
release
=
this
->
evalRelease
();
this
->
setRelease
(
release
);
}
/* -------------------------------------------------------------------------- */
void
Component
::
changeRelease
()
{
LMObject
::
changeRelease
();
for
(
auto
&&
[
name
,
out
]
:
this
->
outputs
)
{
if
(
not
out
.
has_argument
())
continue
;
out
->
acquireContext
(
*
this
);
}
}
/* -------------------------------------------------------------------------- */
bool
Component
::
evalDependencies
()
{
UInt
release
=
this
->
evalRelease
();
if
(
release
!=
this
->
getRelease
())
return
true
;
return
false
;
}
/* -------------------------------------------------------------------------- */
void
Component
::
propagateContextToOutputs
()
{
for
(
auto
&&
[
name
,
out
]
:
this
->
outputs
)
{
if
(
not
out
.
has_value
())
LM_FATAL
(
name
<<
": output was not created/computed/connected"
);
try
{
out
.
get
().
acquireContext
(
*
this
);
}
catch
(...)
{
DUMP
(
name
<<
": output could not receive context"
,
DBG_WARNING
);
}
}
}
/* -------------------------------------------------------------------------- */
UInt
Component
::
evalRelease
()
{
if
(
this
->
inputs
.
size
()
==
0
)
{
return
this
->
getRelease
();
}
std
::
vector
<
UInt
>
release_inputs
;
for
(
auto
&&
[
name
,
inp
]
:
this
->
inputs
)
{
UInt
release
;
if
(
not
inp
.
has_value
())
release
=
LMObject
::
random_release
();
try
{
release
=
inp
.
evalRelease
();
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
return
LMObject
::
random_release
();
}
release_inputs
.
push_back
(
release
);
}
UInt
release
=
hash_vector
(
release_inputs
);
return
release
;
}
/* -------------------------------------------------------------------------- */
void
Component
::
clear
()
{
for
(
auto
&&
[
name
,
out
]
:
this
->
outputs
)
{
this
->
applyArrayOutput
([](
auto
&
output
)
->
void
{
output
.
clear
();
},
name
);
}
}
/* --------------------------------------------------------------------- */
UInt
Component
::
size
(
const
std
::
string
&
name
)
{
try
{
auto
&
_output
=
this
->
getOutput
<
ContainerInterface
>
(
name
);
return
_output
.
size
();
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
// do nothing: cannot clean unallocated pointer
}
catch
(
AutoDispatch
::
bad_argument_cast
&
e
)
{
// do nothing: it is not an array
}
catch
(
std
::
bad_cast
&
e
)
{
// do nothing: it is not an array
}
return
0
;
}
/* --------------------------------------------------------------------- */
__END_LIBMULTISCALE__
/* ---------------------------------------------------------------------- */
Event Timeline
Log In to Comment