Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F10548124
Message.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
10 KB
Referenced Files
None
Subscribers
None
Message.hpp
View Options
/*******************************************************************************
*
* File: Message.hpp
*
* Contents: Declaration of Message base-class.
*
* Copyright 2017
*
* Author: David Juhasz (david.juhasz@tuwien.ac.at)
*
******************************************************************************/
#ifndef ROSA_CORE_MESSAGE_HPP
#define ROSA_CORE_MESSAGE_HPP
#include
"rosa/support/log.h"
#include
"rosa/support/type_token.hpp"
#include
<memory>
#include
<vector>
namespace
rosa
{
// Message interface. The interface provides means to check the type of the
// stored values, but actual data is to be managed by derived implementations.
// Messages are immutable data objects, obtaining their data upon creation and
// providing only constant references for the stored values.
// NOTE: Any reference obtained from a Message instance remains valid only as
// long as the owning Message object is not destroyed.
class
Message
{
protected
:
// Ctor.
// NOTE: No implementation for empty list.
template
<
typename
Type
,
typename
...
Ts
>
Message
(
const
Type
&
,
const
Ts
&
...)
noexcept
;
// No copy and move.
Message
(
const
Message
&
)
=
delete
;
Message
(
Message
&&
)
=
delete
;
Message
&
operator
=
(
const
Message
&
)
=
delete
;
Message
&
operator
=
(
Message
&&
)
=
delete
;
public
:
// Type alias for a smart pointer for Message.
using
message_t
=
std
::
unique_ptr
<
Message
>
;
// Factory function to locally create a Message instance from constant
// references.
template
<
typename
Type
,
typename
...
Types
>
static
message_t
create
(
const
Type
&
T
,
const
Types
&
...
Ts
)
noexcept
;
// Factory function to locally create a Message instance from movable
// references.
template
<
typename
Type
,
typename
...
Types
>
static
message_t
create
(
Type
&&
T
,
Types
&&
...
Ts
)
noexcept
;
// A valid, non-empty token representing the types of the values stored in
// the Message.
const
Token
T
;
// The number of types encoded in T, that is the number of values stored in
// Message.
const
size_t
Size
;
// Virtual dtor.
virtual
~
Message
(
void
);
// Tells if the value in position Pos is of type Type.
// NOTE: Token encodes atoms as AtomValue and not directly AtomConstants.
// PRE: Pos < Size
template
<
typename
Type
>
bool
isTypeAt
(
const
size_t
Pos
)
const
noexcept
;
// Gives a constant reference of the value of type Type in position Pos.
// PRE: Pos < Size && isTypeAt(Pos)
template
<
typename
Type
>
const
Type
&
getValueAt
(
const
size_t
Pos
)
const
noexcept
;
protected
:
// Provides an untyped pointer for the value in position Pos.
// PRE: Pos < Size
virtual
const
void
*
getPointerTo
(
const
size_t
Pos
)
const
noexcept
=
0
;
};
// Nested namespace with an implementation for Message, consider it private.
namespace
{
// Template class for an implementation of Message, definition below.
template
<
typename
...
Types
>
class
LocalMessage
;
// Initializes Arena with values from const references of Types.
// NOTE: Arena needs to be a valid pointer to a memory area big enough for
// values of Types.
template
<
typename
...
Types
>
inline
void
createMessageElements
(
void
*
const
Arena
,
const
Types
&
...
Ts
)
noexcept
;
// NOTE: This terminal case is used for both constant references and movable
// references.
template
<
size_t
Pos
>
inline
void
createMessageElement
(
void
*
const
,
const
std
::
vector
<
size_t
>
&
Offsets
)
{
ASSERT
(
Pos
==
Offsets
.
size
());
}
template
<
size_t
Pos
,
AtomValue
V
,
typename
...
Types
>
inline
void
createMessageElement
(
void
*
const
Arena
,
const
std
::
vector
<
size_t
>
&
Offsets
,
const
AtomConstant
<
V
>
&
,
const
Types
&
...
Ts
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
&&
Pos
<
Offsets
.
size
());
*
static_cast
<
AtomValue
*>
(
static_cast
<
void
*>
(
static_cast
<
uint8_t
*>
(
Arena
)
+
Offsets
[
Pos
]))
=
V
;
createMessageElement
<
Pos
+
1
>
(
Arena
,
Offsets
,
Ts
...);
}
template
<
size_t
Pos
,
typename
Type
,
typename
...
Types
>
inline
void
createMessageElement
(
void
*
const
Arena
,
const
std
::
vector
<
size_t
>
&
Offsets
,
const
Type
&
T
,
const
Types
&
...
Ts
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
&&
Pos
<
Offsets
.
size
());
new
(
static_cast
<
Type
*>
(
static_cast
<
void
*>
(
static_cast
<
uint8_t
*>
(
Arena
)
+
Offsets
[
Pos
])))
Type
(
T
);
createMessageElement
<
Pos
+
1
>
(
Arena
,
Offsets
,
Ts
...);
}
template
<
typename
Type
,
typename
...
Types
>
inline
void
createMessageElements
(
void
*
const
Arena
,
const
Type
&
T
,
const
Types
&
...
Ts
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
);
createMessageElement
<
0
>
(
Arena
,
LocalMessage
<
Type
,
Types
...
>::
Offsets
,
T
,
Ts
...);
}
// Initializes Arena with values from movable references of Types.
// NOTE: Arena needs to be a valid pointer to a memory area big enough for
// values of Types.
template
<
typename
...
Types
>
inline
void
createMessageElements
(
void
*
const
Arena
,
Types
&&
...
Ts
)
noexcept
;
template
<
size_t
Pos
,
AtomValue
V
,
typename
...
Types
>
inline
void
createMessageElement
(
void
*
const
Arena
,
const
std
::
vector
<
size_t
>
&
Offsets
,
AtomConstant
<
V
>
&&
,
Types
&&
...
Ts
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
&&
Pos
<
Offsets
.
size
());
*
static_cast
<
AtomValue
*>
(
static_cast
<
void
*>
(
static_cast
<
uint8_t
*>
(
Arena
)
+
Offsets
[
Pos
]))
=
V
;
createMessageElement
<
Pos
+
1
>
(
Arena
,
Offsets
,
std
::
move
(
Ts
)...);
}
template
<
size_t
Pos
,
typename
Type
,
typename
...
Types
>
inline
void
createMessageElement
(
void
*
const
Arena
,
const
std
::
vector
<
size_t
>
&
Offsets
,
Type
&&
T
,
Types
&&
...
Ts
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
&&
Pos
<
Offsets
.
size
());
new
(
static_cast
<
Type
*>
(
static_cast
<
void
*>
(
static_cast
<
uint8_t
*>
(
Arena
)
+
Offsets
[
Pos
])))
Type
(
std
::
move
(
T
));
createMessageElement
<
Pos
+
1
>
(
Arena
,
Offsets
,
std
::
move
(
Ts
)...);
}
template
<
typename
Type
,
typename
...
Types
>
inline
void
createMessageElements
(
void
*
const
Arena
,
Type
&&
T
,
Types
&&
...
Ts
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
);
createMessageElement
<
0
>
(
Arena
,
LocalMessage
<
Type
,
Types
...
>::
Offsets
,
std
::
move
(
T
),
std
::
move
(
Ts
)...);
}
// Destroyes values of Types stored in Arena.
// NOTE: Arena needs to be a valid pointer to a memory area where values of
// Types are stored.
template
<
typename
Type
,
typename
...
Types
>
inline
void
destroyMessageElements
(
void
*
const
Arena
)
noexcept
;
template
<
size_t
Pos
>
inline
void
destroyMessageElement
(
void
*
const
,
const
std
::
vector
<
size_t
>
&
Offsets
)
noexcept
{
ASSERT
(
Pos
==
Offsets
.
size
());
}
template
<
size_t
Pos
,
typename
Type
,
typename
...
Types
>
inline
void
destroyMessageElement
(
void
*
const
Arena
,
const
std
::
vector
<
size_t
>
&
Offsets
)
noexcept
{
ASSERT
(
Arena
!=
nullptr
&&
Pos
<
Offsets
.
size
());
static_cast
<
Type
*>
(
static_cast
<
void
*>
(
static_cast
<
uint8_t
*>
(
Arena
)
+
Offsets
[
Pos
]))
->~
Type
();
destroyMessageElement
<
Pos
+
1
,
Types
...
>
(
Arena
,
Offsets
);
}
template
<
typename
Type
,
typename
...
Types
>
inline
void
destroyMessageElements
(
void
*
const
Arena
)
noexcept
{
destroyMessageElement
<
0
,
Type
,
Types
...
>
(
Arena
,
LocalMessage
<
Type
,
Types
...
>::
Offsets
);
}
// Implementation of the template LocalMessage. Provides facilities for storing
// values as a Message.
template
<
typename
Type
,
typename
...
Types
>
class
LocalMessage
<
Type
,
Types
...
>
:
public
Message
{
public
:
// Type Token for the stored values.
// NOTE: Only for compile-time checks, static member is not defined.
static
constexpr
Token
ST
=
TypeToken
<
typename
std
::
decay
<
Type
>::
type
,
typename
std
::
decay
<
Types
>::
type
...
>::
Value
;
// Offsets required to access values in Arena.
static
const
std
::
vector
<
size_t
>
Offsets
;
private
:
// A BLOB storing all the values one after the other.
void
*
const
Arena
;
// Generates offset for accessing values in Arena.
static
std
::
vector
<
size_t
>
getOffsets
(
void
)
noexcept
{
Token
T
=
ST
;
// Need a mutable copy.
size_t
I
=
0
;
// Start indexing from position 0.
std
::
vector
<
size_t
>
O
(
lengthOfToken
(
T
));
// Allocate vector of proper size.
O
[
0
]
=
0
;
// First offset is always 0.
while
(
!
emptyToken
(
T
))
{
ASSERT
(
I
<
O
.
size
());
// Calculate next offset based on the previous one.
O
[
I
+
1
]
=
O
[
I
]
+
sizeOfHeadOfToken
(
T
);
dropHeadOfToken
(
T
),
++
I
;
}
ASSERT
(
I
==
O
.
size
());
return
O
;
}
public
:
// Ctor for constant references.
LocalMessage
(
const
Type
&
T
,
const
Types
&
...
Ts
)
noexcept
:
Message
(
T
,
Ts
...),
Arena
(
::
operator
new
(
sizeOfValuesOfToken
(
ST
)))
{
ASSERT
(
this
->
T
==
ST
&&
Size
==
Offsets
.
size
()
&&
Arena
!=
nullptr
);
// Sanity check.
createMessageElements
(
Arena
,
T
,
Ts
...);
}
// Ctor for movable referecens.
LocalMessage
(
Type
&&
T
,
Types
&&
...
Ts
)
noexcept
:
Message
(
T
,
Ts
...),
Arena
(
::
operator
new
(
sizeOfValuesOfToken
(
ST
)))
{
ASSERT
(
this
->
T
==
ST
&&
Size
==
Offsets
.
size
()
&&
Arena
!=
nullptr
);
// Sanity check.
createMessageElements
(
Arena
,
std
::
move
(
T
),
std
::
move
(
Ts
)...);
}
// Dtor.
~
LocalMessage
(
void
)
{
destroyMessageElements
<
Type
,
Types
...
>
(
Arena
);
::
operator
delete
(
Arena
);
}
// Provides an untyped pointer for the constant value at Pos.
const
void
*
getPointerTo
(
const
size_t
Pos
)
const
noexcept
override
{
ASSERT
(
Pos
<
Offsets
.
size
());
return
static_cast
<
uint8_t
*>
(
Arena
)
+
Offsets
[
Pos
];
}
};
// Implementation of the static member field Offsets.
template
<
typename
Type
,
typename
...
Types
>
const
std
::
vector
<
size_t
>
LocalMessage
<
Type
,
Types
...
>::
Offsets
=
LocalMessage
<
Type
,
Types
...
>::
getOffsets
();
}
// End namespace
template
<
typename
Type
,
typename
...
Ts
>
Message
::
Message
(
const
Type
&
,
const
Ts
&
...)
noexcept
:
T
(
TypeToken
<
typename
std
::
decay
<
Type
>::
type
,
typename
std
::
decay
<
Ts
>::
type
...
>::
Value
),
Size
(
lengthOfToken
(
T
))
{
ASSERT
(
validToken
(
T
)
&&
lengthOfToken
(
T
)
==
(
1
+
sizeof
...(
Ts
)));
// Sanity check.
LOG_TRACE
(
"Creating Message with Token("
+
to_string
(
T
)
+
")"
);
}
template
<
typename
Type
,
typename
...
Types
>
Message
::
message_t
Message
::
create
(
const
Type
&
T
,
const
Types
&
...
Ts
)
noexcept
{
return
message_t
(
new
LocalMessage
<
Type
,
Types
...
>
(
T
,
Ts
...));
}
template
<
typename
Type
,
typename
...
Types
>
Message
::
message_t
Message
::
create
(
Type
&&
T
,
Types
&&
...
Ts
)
noexcept
{
return
message_t
(
new
LocalMessage
<
Type
,
Types
...
>
(
std
::
move
(
T
),
std
::
move
(
Ts
)...));
}
template
<
typename
Type
>
bool
Message
::
isTypeAt
(
const
size_t
Pos
)
const
noexcept
{
ASSERT
(
Pos
<
Size
);
Token
T_
=
T
;
// NOLINT
dropNOfToken
(
T_
,
Pos
);
return
isHeadOfTokenTheSameType
<
Type
>
(
T_
);
}
template
<
typename
Type
>
const
Type
&
Message
::
getValueAt
(
const
size_t
Pos
)
const
noexcept
{
ASSERT
(
Pos
<
Size
&&
isTypeAt
<
Type
>
(
Pos
));
return
*
static_cast
<
const
Type
*>
(
getPointerTo
(
Pos
));
}
}
// End namespace rosa
#endif
// ROSA_CORE_MESSAGE_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, May 30, 11:49 PM (22 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
329127
Default Alt Text
Message.hpp (10 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment