Skip to content

Commit fb2badc

Browse files
committed
Release v1.1
2 parents ce18bdd + a1a2601 commit fb2badc

33 files changed

+6654
-952
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ set (DATA_INSTALL_REL_DIR ${CMAKE_INSTALL_DATAROOTDIR}/${INSTALL_NAME})
160160
set (DATA_INSTALL_DIR ${INSTALL_DIR}/${DATA_INSTALL_REL_DIR})
161161
set (DOC_INSTALL_DIR ${INSTALL_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/doc)
162162
set (ICON_INSTALL_DIR ${DATA_INSTALL_DIR}/icon)
163-
set (CONFIG_INSTALL_REL_DIR ${CMAKE_INSTALL_SYSCONFDIR}/${INSTALL_NAME})
163+
set (CONFIG_INSTALL_REL_DIR ${CMAKE_INSTALL_DATADIR}/${INSTALL_NAME})
164164
set (CONFIG_INSTALL_DIR ${INSTALL_DIR}/${CONFIG_INSTALL_REL_DIR})
165165

166166
install (DIRECTORY cmake DESTINATION ${LIB_INSTALL_DIR}/${INSTALL_NAME})

comms/doc/comms.dox

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
/// @namespace comms::traits::units
2929
/// @brief Namespace for various traits tag classes used in units conversion operations.
3030

31+
/// @namespace comms::traits::dispatch
32+
/// @brief Namespace for various traits tag classes used in dispatch operations.
33+
3134
/// @namespace comms::units
3235
/// @brief Namespace containing units conversion operations
3336

comms/doc/page_dispatch.dox

Lines changed: 594 additions & 0 deletions
Large diffs are not rendered by default.

comms/doc/page_use_prot.dox

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,10 @@
24412441
/// third template parameter (which defaults to @b void), can be used to
24422442
/// specify the return type of handling functions.
24432443
///
2444+
/// @b NOTE, since version @b v1.1 the @b COMMS library supports other
2445+
/// ways to dispatch a message object to its handling function in addition
2446+
/// to one described above. Please read @ref page_dispatch page for more details.
2447+
///
24442448
/// @section page_use_prot_extra_transport Extra Transport Values
24452449
/// Some protocols may use extra values in their transport information, which
24462450
/// may influence the way how message payload is being read and/or message

comms/include/comms/MsgFactory.h

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include "comms/util/Tuple.h"
2828
#include "comms/util/alloc.h"
2929
#include "details/MsgFactoryOptionsParser.h"
30-
#include "details/MsgFactorySelector.h"
30+
#include "details/MsgFactoryBase.h"
3131

3232
namespace comms
3333
{
@@ -39,8 +39,7 @@ namespace comms
3939
/// embedded environment.@n
4040
/// The types of all messages provided in @b TAllMessages are analysed at
4141
/// compile time and best "id to message object" mapping strategy is chosen,
42-
/// whether it is direct access array (with O(1) time complexity) or
43-
/// sorted array with binary search (with O(log(n)) time complexity).
42+
/// unless the "dispatch" type forcing options are used (see description below).
4443
/// @tparam TMsgBase Common base class for all the messages, smart pointer to
4544
/// this type is returned when allocation of specify message is requested.
4645
/// @tparam TAllMessages All custom message types, that this factory is capable
@@ -72,60 +71,88 @@ namespace comms
7271
/// the base class of @ref comms::GenericMessage type (first template
7372
/// parameter) must be equal to @b TMsgBase (first template parameter)
7473
/// of @b this class.
74+
/// @li @ref comms::option::ForceDispatchPolymorphic,
75+
/// @ref comms::option::ForceDispatchStaticBinSearch, or
76+
/// @ref comms::option::ForceDispatchLinearSwitch - Force a particular
77+
/// dispatch way when creating message object given the numeric ID
78+
/// (see @ref comms::MsgFactory::createMsg()). The dispatch methods
79+
/// are properly described in @ref page_dispatch tutorial page.
80+
/// If none of these options are provided, then the MsgFactory
81+
/// used a default way, which is equivalent to calling
82+
/// @ref comms::dispatchMsgType() (see also @ref page_dispatch_message_type_default).
83+
/// To inquire what actual dispatch type is used, please use one
84+
/// of the following constexpr member functions:
85+
/// @ref comms::MsgFactory::isDispatchPolymorphic(),
86+
/// @ref comms::MsgFactory::isDispatchStaticBinSearch(), and
87+
/// @ref comms::MsgFactory::isDispatchLinearSwitch()
7588
/// @pre TMsgBase is a base class for all the messages in TAllMessages.
7689
/// @pre Message type is TAllMessages must be sorted based on their IDs.
7790
/// @pre If comms::option::InPlaceAllocation option is provided, only one custom
7891
/// message can be allocated. The next one can be allocated only after previous
7992
/// message has been destructed.
8093
/// @headerfile comms/MsgFactory.h
8194
template <typename TMsgBase, typename TAllMessages, typename... TOptions>
82-
class MsgFactory
95+
class MsgFactory : private details::MsgFactoryBase<TMsgBase, TAllMessages, TOptions...>
8396
{
97+
using Base = details::MsgFactoryBase<TMsgBase, TAllMessages, TOptions...>;
8498
static_assert(TMsgBase::InterfaceOptions::HasMsgIdType,
8599
"Usage of MsgFactory requires Message interface to provide ID type. "
86100
"Use comms::option::MsgIdType option in message interface type definition.");
87101

88-
using Factory = typename
89-
details::MsgFactorySelector<TMsgBase, TAllMessages, TOptions...>::Type;
90-
91102
public:
92103
/// @brief Parsed options
93-
using ParsedOptions = typename Factory::ParsedOptions;
104+
using ParsedOptions = typename Base::ParsedOptions;
94105

95106
/// @brief Type of the common base class of all the messages.
96-
using Message = TMsgBase;
107+
using Message = typename Base::Message;
97108

98109
/// @brief Type of the message ID when passed as a parameter.
99-
using MsgIdParamType = typename Message::MsgIdParamType;
110+
using MsgIdParamType = typename Base::MsgIdParamType;
100111

101112
/// @brief Type of the message ID.
102-
using MsgIdType = typename Message::MsgIdType;
113+
using MsgIdType = typename Base::MsgIdType;
103114

104115
/// @brief Smart pointer to @ref Message which holds allocated message object.
105116
/// @details It is a variant of std::unique_ptr, based on whether
106117
/// comms::option::InPlaceAllocation option was used.
107-
using MsgPtr = typename Factory::MsgPtr;
118+
using MsgPtr = typename Base::MsgPtr;
108119

109120
/// @brief All messages provided as template parameter to this class.
110-
using AllMessages = TAllMessages;
121+
using AllMessages = typename Base::AllMessages;
122+
123+
#ifdef FOR_DOXYGEN_DOC_ONLY
124+
// @brief Reason for message creation failure
125+
enum class CreateFailureReason
126+
{
127+
None, ///< No reason
128+
InvalidId, ///< Invalid message id
129+
AllocFailure, ///< Allocation of the object has failied
130+
NumOfValues ///< Number of available values, must be last
131+
};
132+
#else // #ifdef FOR_DOXYGEN_DOC_ONLY
133+
using CreateFailureReason = typename Base::CreateFailureReason;
134+
#endif // #ifdef FOR_DOXYGEN_DOC_ONLY
111135

112136
/// @brief Create message object given the ID of the message.
137+
/// @details The id to mapping is performed using the chosen (or default)
138+
/// @b dispatch policy described in the class options.
113139
/// @param id ID of the message.
114-
/// @param idx Relative index of the message with the same ID. In case
140+
/// @param idx Relative index (or offset) of the message with the same ID. In case
115141
/// protocol implementation contains multiple distinct message types
116142
/// that report same ID value, it must be possible to choose the
117143
/// relative index of such message from the first message type reporting
118144
/// the same ID. This parameter provides such an ability. However,
119145
/// most protocols will implement single message class for single ID.
120146
/// For such implementations, use default value of this parameter.
147+
/// @param[out] reason Failure reason in case creation has failed. May be nullptr.
121148
/// @return Smart pointer (variant of std::unique_ptr) to @ref Message type,
122149
/// which is a common base class of all the messages (provided as
123150
/// first template parameter to this class). If comms::option::InPlaceAllocation
124151
/// option was used and previously allocated message wasn't de-allocated
125152
/// yet, the empty (null) pointer will be returned.
126-
MsgPtr createMsg(MsgIdParamType id, unsigned idx = 0) const
153+
MsgPtr createMsg(MsgIdParamType id, unsigned idx = 0, CreateFailureReason* reason = nullptr) const
127154
{
128-
return factory_.createMsg(id, idx);
155+
return Base::createMsg(id, idx, reason);
129156
}
130157

131158
/// @brief Allocate and initialise @ref comms::GenericMessage object.
@@ -136,26 +163,59 @@ class MsgFactory
136163
/// constructor of the @ref comms::GenericMessage class
137164
MsgPtr createGenericMsg(MsgIdParamType id) const
138165
{
139-
return factory_.createGenericMsg(id);
166+
return Base::createGenericMsg(id);
140167
}
141168

169+
/// @brief Inquiry whether allocation is possible
170+
bool canAllocate() const
171+
{
172+
return Base::canAllocate();
173+
}
142174
/// @brief Get number of message types from @ref AllMessages, that have the specified ID.
143175
/// @param id ID of the message.
144176
/// @return Number of message classes that report same ID.
145177
std::size_t msgCount(MsgIdParamType id) const
146178
{
147-
return factory_.msgCount(id);
179+
return Base::msgCount(id);
148180
}
149181

150-
/// @brief Compile time knowldege inquiry whether all the message classes in the
182+
/// @brief Compile time inquiry whether all the message classes in the
151183
/// @b TAllMessages bundle have unique IDs.
152184
static constexpr bool hasUniqueIds()
153185
{
154-
return Factory::hasUniqueIds();
186+
return Base::hasUniqueIds();
187+
}
188+
189+
/// @brief Compile time inquiry whether polymorphic dispatch tables are
190+
/// generated internally to map message ID to actual type.
191+
/// @see @ref page_dispatch
192+
/// @see @ref comms::MsgFactory::isDispatchStaticBinSearch()
193+
/// @see @ref comms::MsgFactory::isDispatchLinearSwitch()
194+
static constexpr bool isDispatchPolymorphic()
195+
{
196+
return Base::isDispatchPolymorphic();
197+
}
198+
199+
/// @brief Compile time inquiry whether static binary search dispatch is
200+
/// generated internally to map message ID to actual type.
201+
/// @see @ref page_dispatch
202+
/// @see @ref comms::MsgFactory::isDispatchPolymorphic()
203+
/// @see @ref comms::MsgFactory::isDispatchLinearSwitch()
204+
static constexpr bool isDispatchStaticBinSearch()
205+
{
206+
return Base::isDispatchStaticBinSearch();
207+
}
208+
209+
/// @brief Compile time inquiry whether linear switch dispatch is
210+
/// generated internally to map message ID to actual type.
211+
/// @see @ref page_dispatch
212+
/// @see @ref comms::MsgFactory::isDispatchStaticBinSearch()
213+
/// @see @ref comms::MsgFactory::isDispatchLinearSwitch()
214+
static constexpr bool isDispatchLinearSwitch()
215+
{
216+
return Base::isDispatchLinearSwitch();
155217
}
156218

157-
private:
158-
Factory factory_;
159219
};
160220

161221

comms/include/comms/comms.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "protocols.h"
2626
#include "units.h"
2727
#include "version.h"
28+
#include "dispatch.h"
29+
#include "field_cast.h"
2830

2931
#include "Message.h"
3032
#include "EmptyHandler.h"
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// Copyright 2019 (C). Alex Robenko. All rights reserved.
3+
//
4+
5+
// This library is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
#pragma once
19+
20+
#include <type_traits>
21+
#include <limits>
22+
23+
#include "comms/Message.h"
24+
#include "comms/MessageBase.h"
25+
#include "comms/util/Tuple.h"
26+
#include "comms/details/message_check.h"
27+
#include "comms/CompileControl.h"
28+
29+
namespace comms
30+
{
31+
32+
namespace details
33+
{
34+
35+
template <typename TMessage>
36+
class DispatchMsgIdRetrieveHelper
37+
{
38+
public:
39+
static_assert(TMessage::hasMsgIdType(), "Message interface class must define its id type");
40+
using MsgIdParamType = typename TMessage::MsgIdParamType;
41+
using MsgIdType = typename TMessage::MsgIdType;
42+
43+
static MsgIdParamType doGetId()
44+
{
45+
using Tag =
46+
typename std::conditional<
47+
messageHasStaticNumId<TMessage>(),
48+
HasStaticIdTag,
49+
typename std::conditional<
50+
comms::isMessage<TMessage>() && TMessage::hasGetId(),
51+
HasDynamicIdTag,
52+
NoIdTag
53+
>::type
54+
>::type;
55+
56+
static_assert(!std::is_same<Tag, NoIdTag>::value, "Must be able to retrieve ID");
57+
return doGetIdInternal(Tag());
58+
}
59+
60+
private:
61+
struct HasStaticIdTag {};
62+
struct HasDynamicIdTag {};
63+
struct NoIdTag {};
64+
65+
static MsgIdParamType doGetIdInternal(HasStaticIdTag)
66+
{
67+
static_assert(comms::isMessageBase<TMessage>(), "Must be actual message");
68+
static_assert(messageHasStaticNumId<TMessage>(), "Message must define static numeric ID");
69+
70+
return TMessage::doGetId();
71+
}
72+
73+
static MsgIdParamType doGetIdInternal(HasDynamicIdTag)
74+
{
75+
static_assert(comms::isMessage<TMessage>(), "Must be actual message");
76+
static_assert(TMessage::hasGetId(), "Message interface must be able to return id polymorphically");
77+
78+
static const MsgIdType Id = TMessage().getId();
79+
return Id;
80+
}
81+
};
82+
83+
template <typename TMessage>
84+
auto dispatchMsgGetMsgId() -> decltype(DispatchMsgIdRetrieveHelper<TMessage>::doGetId())
85+
{
86+
return DispatchMsgIdRetrieveHelper<TMessage>::doGetId();
87+
}
88+
89+
} // namespace details
90+
91+
} // namespace comms

0 commit comments

Comments
 (0)