Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1497181
DeluxeAgent.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
9 KB
Referenced Files
None
Subscribers
None
DeluxeAgent.cpp
View Options
//===-- deluxe/DeluxeAgent.cpp ----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file deluxe/DeluxeAgent.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Implementation of rosa/deluxe/DeluxeAgent.hpp.
///
//===----------------------------------------------------------------------===//
#include
"rosa/deluxe/DeluxeAgent.hpp"
#include
"rosa/deluxe/DeluxeSystem.hpp"
#include
<algorithm>
namespace
rosa
{
namespace
deluxe
{
bool
DeluxeAgent
::
inv
(
void
)
const
noexcept
{
// Check execution policy.
// \note The \c rosa::System the \c rosa::Unit is created with is a
// \c rosa::DeluxeSystem.
const
DeluxeSystem
&
DS
=
static_cast
<
DeluxeSystem
&>
(
Unit
::
system
());
if
(
!
ExecutionPolicy
||
!
ExecutionPolicy
->
canHandle
(
Self
,
DS
))
{
return
false
;
}
// Check number of inputs and master-outputs.
if
(
NumberOfInputs
!=
NumberOfMasterOutputs
)
{
return
false
;
}
// Check container sizes.
if
(
!
(
InputTypes
.
size
()
==
NumberOfInputs
&&
InputNextPos
.
size
()
==
NumberOfInputs
&&
InputChanged
.
size
()
==
NumberOfInputs
&&
InputValues
.
size
()
==
NumberOfInputs
&&
MasterOutputTypes
.
size
()
==
NumberOfInputs
// == NumberOfMasterOutputs
&&
Slaves
.
size
()
==
NumberOfInputs
))
{
return
false
;
}
// Check *slave* types and validate *slave* registrations and reverse lookup
// information.
std
::
map
<
id_t
,
size_t
>
RefIds
;
// Build up a reference of SlaveIds in this.
for
(
size_t
I
=
0
;
I
<
NumberOfInputs
;
++
I
)
{
// Fetch type-related information for the input position.
const
Token
T
=
InputTypes
[
I
];
const
token_size_t
TL
=
lengthOfToken
(
T
);
// Validate size of storage at position \c I.
if
(
InputValues
[
I
]
->
size
()
!=
TL
)
{
return
false
;
}
// Validate input types at position \c I.
for
(
token_size_t
TI
=
0
;
TI
<
TL
;
++
TI
)
{
if
(
InputValues
[
I
]
->
typeAt
(
static_cast
<
token_size_t
>
(
TI
))
!=
typeAtPositionOfToken
(
T
,
TI
))
{
return
false
;
}
}
// Check the index of next expected element for position \c I.
if
(
InputNextPos
[
I
]
>=
TL
)
{
return
false
;
}
// Check the registered *slave* at position \c I.
const
auto
&
Slave
=
Slaves
[
I
];
// If \c Slave is empty, nothing to check.
if
(
!
Slave
)
continue
;
// Prepare master-output related info for the *slave*.
const
Token
MT
=
MasterOutputTypes
[
I
];
const
bool
hasMT
=
!
emptyToken
(
MT
);
// \c Slave is not empty here.
// Check the `OutputType` and `MasterInputType` of the registered *slave*.
const
auto
&
A
=
unwrapAgent
(
*
Slave
);
if
(
!
((
A
.
Kind
==
atoms
::
SensorKind
&&
static_cast
<
const
DeluxeSensor
&>
(
A
).
OutputType
==
T
&&
(
!
hasMT
||
static_cast
<
const
DeluxeSensor
&>
(
A
).
MasterInputType
==
MT
))
||
(
A
.
Kind
==
atoms
::
AgentKind
&&
static_cast
<
const
DeluxeAgent
&>
(
A
).
OutputType
==
T
&&
(
!
hasMT
||
static_cast
<
const
DeluxeAgent
&>
(
A
).
MasterInputType
==
MT
))))
{
return
false
;
}
// Validate that the *slave* is not registered more than once.
if
(
std
::
any_of
(
Slaves
.
begin
()
+
I
+
1
,
Slaves
.
end
(),
[
&
Slave
](
const
Optional
<
AgentHandle
>
&
O
)
{
return
O
&&
*
Slave
==
*
O
;
}))
{
return
false
;
}
// Build the content of \c RefIds.
RefIds
.
emplace
(
A
.
Id
,
I
);
}
// Validate *slave* reverse lookup information against our reference.
if
(
RefIds
!=
SlaveIds
)
{
return
false
;
}
// Check the size of the master-input storage.
if
(
MasterInputValue
->
size
()
!=
lengthOfToken
(
MasterInputType
))
{
return
false
;
}
// Check the index of next expected element from the *master*.
const
token_size_t
MITL
=
lengthOfToken
(
MasterInputType
);
if
((
MITL
!=
0
&&
MasterInputNextPos
>=
MITL
)
||
(
MITL
==
0
&&
MasterInputNextPos
!=
0
))
{
return
false
;
}
// All checks were successful, the invariant is held.
return
true
;
}
DeluxeAgent
::~
DeluxeAgent
(
void
)
noexcept
{
ASSERT
(
inv
());
LOG_TRACE_STREAM
<<
"Destroying DeluxeAgent "
<<
FullName
<<
"..."
<<
std
::
endl
;
// Make sure \p this object is not a registered *slave*.
if
(
Master
)
{
ASSERT
(
unwrapAgent
(
*
Master
).
Kind
==
atoms
::
AgentKind
);
// Sanity check.
DeluxeAgent
&
M
=
static_cast
<
DeluxeAgent
&>
(
unwrapAgent
(
*
Master
));
ASSERT
(
M
.
positionOfSlave
(
self
())
!=
M
.
NumberOfInputs
);
// Sanity check.
M
.
registerSlave
(
M
.
positionOfSlave
(
self
()),
{});
Master
=
{};
}
// Also, make sure \p this object is no acting *master*.
for
(
size_t
Pos
=
0
;
Pos
<
NumberOfInputs
;
++
Pos
)
{
registerSlave
(
Pos
,
{});
}
// Now there is no connection with other entities, safe to destroy.
}
id_t
DeluxeAgent
::
masterId
(
void
)
const
noexcept
{
ASSERT
(
inv
()
&&
Master
);
return
unwrapAgent
(
*
Master
).
Id
;
}
const
DeluxeExecutionPolicy
&
DeluxeAgent
::
executionPolicy
(
void
)
const
noexcept
{
ASSERT
(
inv
());
return
*
ExecutionPolicy
;
}
bool
DeluxeAgent
::
setExecutionPolicy
(
std
::
unique_ptr
<
DeluxeExecutionPolicy
>
&&
EP
)
noexcept
{
ASSERT
(
inv
());
LOG_TRACE_STREAM
<<
"DeluxeAgent "
<<
FullName
<<
" setting execution policy "
<<
*
EP
<<
std
::
endl
;
bool
Success
=
false
;
// \note The \c rosa::System the \c rosa::Unit is created with is a
// \c rosa::DeluxeSystem.
const
DeluxeSystem
&
DS
=
static_cast
<
DeluxeSystem
&>
(
Unit
::
system
());
if
(
EP
&&
EP
->
canHandle
(
self
(),
DS
))
{
ExecutionPolicy
.
swap
(
EP
);
Success
=
true
;
}
else
{
LOG_TRACE_STREAM
<<
"Execution policy "
<<
*
EP
<<
" cannot handle DeluxeAgent "
<<
FullName
<<
std
::
endl
;
}
ASSERT
(
inv
());
return
Success
;
}
Optional
<
AgentHandle
>
DeluxeAgent
::
master
(
void
)
const
noexcept
{
ASSERT
(
inv
());
return
Master
;
}
void
DeluxeAgent
::
registerMaster
(
const
Optional
<
AgentHandle
>
_Master
)
noexcept
{
ASSERT
(
inv
()
&&
(
!
_Master
||
unwrapAgent
(
*
_Master
).
Kind
==
atoms
::
AgentKind
));
Master
=
_Master
;
ASSERT
(
inv
());
}
Token
DeluxeAgent
::
inputType
(
const
size_t
Pos
)
const
noexcept
{
ASSERT
(
inv
()
&&
Pos
<
NumberOfInputs
);
return
InputTypes
[
Pos
];
}
Token
DeluxeAgent
::
masterOutputType
(
const
size_t
Pos
)
const
noexcept
{
ASSERT
(
inv
()
&&
Pos
<
NumberOfMasterOutputs
);
return
MasterOutputTypes
[
Pos
];
}
Optional
<
AgentHandle
>
DeluxeAgent
::
slave
(
const
size_t
Pos
)
const
noexcept
{
ASSERT
(
inv
()
&&
Pos
<
NumberOfInputs
);
return
Slaves
[
Pos
];
}
void
DeluxeAgent
::
registerSlave
(
const
size_t
Pos
,
const
Optional
<
AgentHandle
>
Slave
)
noexcept
{
ASSERT
(
inv
()
&&
Pos
<
NumberOfInputs
&&
(
!
Slave
||
(
unwrapAgent
(
*
Slave
).
Kind
==
atoms
::
SensorKind
&&
static_cast
<
const
DeluxeSensor
&>
(
unwrapAgent
(
*
Slave
)).
OutputType
==
InputTypes
[
Pos
]
&&
(
emptyToken
(
MasterOutputTypes
[
Pos
])
||
static_cast
<
const
DeluxeSensor
&>
(
unwrapAgent
(
*
Slave
))
.
MasterInputType
==
MasterOutputTypes
[
Pos
]))
||
(
unwrapAgent
(
*
Slave
).
Kind
==
atoms
::
AgentKind
&&
static_cast
<
const
DeluxeAgent
&>
(
unwrapAgent
(
*
Slave
)).
OutputType
==
InputTypes
[
Pos
]
&&
(
emptyToken
(
MasterOutputTypes
[
Pos
])
||
static_cast
<
const
DeluxeAgent
&>
(
unwrapAgent
(
*
Slave
))
.
MasterInputType
==
MasterOutputTypes
[
Pos
]))));
// If registering an actual *slave*, not just clearing the slot, make sure
// the same *slave* is not registered to another slot.
if
(
Slave
)
{
auto
It
=
SlaveIds
.
find
(
unwrapAgent
(
*
Slave
).
Id
);
if
(
It
!=
SlaveIds
.
end
())
{
Slaves
[
It
->
second
]
=
{};
//Optional<AgentHandle>();
SlaveIds
.
erase
(
It
);
}
}
// Obtain the place whose content is to be replaced with \p Slave
auto
&
OldSlave
=
Slaves
[
Pos
];
// If there is already a *slave* registered at \p Pos, clear reverse lookup
// information for it, and make sure it no longer has \p this object as
// *master*.
if
(
OldSlave
)
{
auto
&
A
=
unwrapAgent
(
*
OldSlave
);
ASSERT
(
SlaveIds
.
find
(
A
.
Id
)
!=
SlaveIds
.
end
());
// Sanity check.
SlaveIds
.
erase
(
A
.
Id
);
if
(
A
.
Kind
==
atoms
::
AgentKind
)
{
static_cast
<
DeluxeAgent
&>
(
A
).
registerMaster
({});
}
else
{
ASSERT
(
A
.
Kind
==
atoms
::
SensorKind
);
// Sanity check.
static_cast
<
DeluxeSensor
&>
(
A
).
registerMaster
({});
}
}
// Register \p Slave at \p Pos.
OldSlave
=
Slave
;
// If registering an actual *slave*, not just clearing the slot, register
// reverse lookup information for the new *slave*.
if
(
Slave
)
{
SlaveIds
.
emplace
(
unwrapAgent
(
*
Slave
).
Id
,
Pos
);
}
ASSERT
(
inv
());
}
size_t
DeluxeAgent
::
positionOfSlave
(
const
AgentHandle
Slave
)
const
noexcept
{
ASSERT
(
inv
());
bool
Found
=
false
;
size_t
Pos
=
0
;
while
(
!
Found
&&
Pos
<
NumberOfInputs
)
{
auto
&
ExistingSlave
=
Slaves
[
Pos
];
if
(
ExistingSlave
&&
*
ExistingSlave
==
Slave
)
{
Found
=
true
;
}
else
{
++
Pos
;
}
}
ASSERT
(
Found
||
Pos
==
NumberOfInputs
);
// Sanity check.
return
Pos
;
}
void
DeluxeAgent
::
handleTrigger
(
atoms
::
Trigger
)
noexcept
{
ASSERT
(
inv
());
FP
();
ASSERT
(
inv
());
}
}
// End namespace deluxe
}
// End namespace rosa
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Mar 1, 9:29 PM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
281286
Default Alt Text
DeluxeAgent.cpp (9 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment