Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F27032889
DeluxeAgent.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Authored By
Unknown
Size
9 KB
Referenced Files
None
Subscribers
None
DeluxeAgent.cpp
View Options
//===-- deluxe/DeluxeAgent.cpp ----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \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
&&
InputStorageOffsets
.
size
()
==
NumberOfInputs
&&
InputValues
->
size
()
==
InputStorageOffsets
[
NumberOfInputs
-
1
]
+
lengthOfToken
(
InputTypes
[
NumberOfInputs
-
1
])
&&
MasterOutputTypes
.
size
()
==
NumberOfInputs
// == NumberOfMasterOutputs
&&
Slaves
.
size
()
==
NumberOfInputs
))
{
return
false
;
}
// Stores storage offset for the next slave position checked in the following
// loop.
token_size_t
InputStorageOffset
=
0
;
// 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
)
{
// First, validate the corresponding storage offset value.
if
(
InputStorageOffsets
[
I
]
!=
InputStorageOffset
)
{
return
false
;
}
// Fetch type-related information for the input position.
const
Token
T
=
InputTypes
[
I
];
const
token_size_t
TL
=
lengthOfToken
(
T
);
const
size_t
StorageOffset
=
InputStorageOffsets
[
I
];
// Update storage offset for the next position.
InputStorageOffset
+=
TL
;
// Validate input types at position \c I.
for
(
token_size_t
TI
=
0
;
TI
<
TL
;
++
TI
)
{
const
size_t
ElemOffset
=
StorageOffset
+
TI
;
// The assert must hold if \p this object was successfuuly constructed.
ASSERT
(
static_cast
<
size_t
>
(
static_cast
<
token_size_t
>
(
ElemOffset
))
==
ElemOffset
);
if
(
InputValues
->
typeAt
(
static_cast
<
token_size_t
>
(
ElemOffset
))
!=
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
Tue, Oct 27, 3:23 PM (21 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
407197
Default Alt Text
DeluxeAgent.cpp (9 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline