Messages

The MARTe messaging mechanism allows components to exchange information and commands based on the Objects addresses (source and destination) in the ObjectRegistryDatabase.

Messages enable to change the behaviour of an application based only on configuration data, i.e. without requiring any code recompilation.

Messages also provide a generic interface between MARTe components and any components and protocols that live outside a MARTe application. This allows, for instance, to replace an external component without changing the internal message protocol.

This interface is typically used for non real-time activities, such as configuration and state management. In particular, messages are the main technology behind the StateMachine

../../_images/Messages-0.png

The main actors are the Message and the MessageI components. The former defines the payload, the sender and the destination of the message. The latter is the interface that allows to receive messages.

Message

The Message requires the definition of the following parameters:

  • Sender: the Object that is sending the message;

  • Destination: the Object that will receive the message;

  • Function: a string which identifies the scope of the action to be performed in the Destination object;

  • IsReply: true if this message is a reply to a previous message;

  • ExpectsReply: true if a reply is expected from the Destination component.

../../_images/Messages-1.png

Given that the Message is also a ReferenceContainer the payload is defined by the References that are inserted into the container.

MessageI

In order to be able to receive messages a component shall inherit from MessageI and shall register one or more filters that will be responsible for deciding if a given message is to be accepted.

Filters shall inherit from MessageFilter and can be either permanent or temporary. A temporary filter will be removed from the MessageI after accepting the first message.

class MessageFilterEx1: public MARTe::Object, public MARTe::MessageFilter {
   ...
   //Permanent filter => MessageFilter(true)
   MessageFilterEx1 () : MARTe::Object(), MARTe::MessageFilter(true) {
   }

   virtual MARTe::ErrorManagement::ErrorType ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
      //Check if this filter is appropriate to handle the message
   }
class MessageEx1: public MARTe::Object, public MARTe::MessageI {
   ...
   MessageEx1 () : MARTe::Object(), MARTe::MessageI() {
     filter = ReferenceT<MessageFilterEx1>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
     filter->SetOwner(this);
     //Install the filter
     ErrorManagement::ErrorType ret = MessageI::InstallMessageFilter(filter);
 }
../../_images/Messages-2.png ../../_images/Messages-3.png

A Message is sent by calling the function MessageI::SendMessage and may be called in any context and from any component (even if it does not inherit from Object).

...
ErrorManagement::ErrorType err = MessageI::SendMessage(msg, this);
...

Replies

The reply to a message can be either direct or indirect. In both cases the same Message instance is used for the reply. The replier is allowed to change the payload as needed.

In the case of a direct reply, the sender waits (polls) for the Message instance to change from IsReply() == false to IsReply() == true. As such, the message sender does not have to inherit from MessageI. The only requirement is that it inherits from Object.

../../_images/Messages-6.png

Original message instance …

../../_images/Messages-4.png

… is changed to update the Destination field to the original sender (note that IsReply() is now true).

../../_images/Messages-5.png
...
//This function will poll and wait for msg->IsReply() to be changed to true
err = MessageI::SendMessageAndWaitReply(msg, this);
...

Conversely, indirect replies require the sender to inherit from MessageI. The reason is that indirect replies are treated as a normal message, but sent back from the replier to the sender.

../../_images/Messages-7.png ../../_images/Messages-4A.png

Indirect replies can be used, for instance, to implement asynchronous message exchanging, allowing, for example, to wait for the reply in the context of a different thread (e.g. by using a QueuedReplyMessageCatcherFilter).

...
//This function will automatically register a ReplyMessageCatcherMessageFilter filter and poll for the message to arrive. It is functionally equivalent
err = SendMessageAndWaitIndirectReply(msg, this);
...
if (messageToTest->ExpectsIndirectReply()) {
   messageToTest->SetAsReply(true);
   //Indirect reply... resend the message
   err = MessageI::SendMessage(messageToTest, this);
}

The type of reply is encoded in the Message configuration using the Mode field.

+Msg1 = {
   Class = Message
   Destination = "MsgRec1"
   Function = "Function0"
   Mode = "ExpectsIndirectReply"
}

Filters

As explained above, the messages are trapped by the MessageFilter components.

The framework offers a set of standard filters that are ready to be used:

Filter

Description

ObjectRegistryDatabaseMessageFilter

Allows to manage (purge and load) the ObjectRegistryDatabase and thus change the configuration of the application in runtime (see example below).

RegisteredMethodsMessageFilter

Enables the call of remote Object functions using messages (see below).

ReplyMessageCatcherMessageFilter

Waits for a given reply to arrive. Typically used with indirect messages.

QueueingMessageFilter

Listens for messages in the context of a different thread and puts the messages in a queue (shall be used with a QueuedMessageI).

QueuedReplyMessageCatcherFilter

Similar to the ReplyMessageCatcherMessageFilter but waits for the message in the context of a different thread.

Note

The message sender does not know what filter will be used to consume the message. As such, it cannot make any assumptions on how the message will be handled (e.g. threading context, existence of a queue, …).

Note

The type of filter does not depend on the fact of the message being sent with a direct or an indirect reply.

Remote function calls

One of the most powerful features of this interface is the possibility of registering functions that can be called using messages.

The prototype of the function to be registered shall be one of (where T is any of the basic types, including StreamString:vcisdoxygencl:):

ErrorManagement::ErrorType (*) ();
ErrorManagement::ErrorType (*) (T param1);
ErrorManagement::ErrorType (*) (T param1, T param2);
ErrorManagement::ErrorType (*) (T param1, T param2, T param3);
ErrorManagement::ErrorType (*) (T param1, T param2, T param3, T param4);

Note

Constantness and in/output declaration of the parameter will be respected. In particular, output parameters will be updated, with the values changed during the function execution, in the message reply.

The methods are registered with the macro CLASS_METHOD_REGISTER (requires including CLASSMETHODREGISTER.h). The class registering functions shall also inherit from MessageI and register a RegisteredMethodsMessageFilter:

class MessageEx1: public MARTe::Object, public MARTe::MessageI {
...
MessageEx1 () : MARTe::Object(), MARTe::MessageI() {
   ...
   filter = ReferenceT<RegisteredMethodsMessageFilter>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
   filter->SetDestination(this);
   ...
}

...
MARTe::ErrorManagement::ErrorType Function0 () {
    REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "Function0 called.");
    return MARTe::ErrorManagement::NoError;
}

MARTe::ErrorManagement::ErrorType Function1 (MARTe::uint32 a, MARTe::float32 b) {
    REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "Received %u %f.", a, b);
    return MARTe::ErrorManagement::NoError;
}
...
CLASS_REGISTER(MessageEx1, "")
CLASS_METHOD_REGISTER(MessageEx1, Function0)
CLASS_METHOD_REGISTER(MessageEx1, Function1)

Note

The following functions prototypes can also be registered but, as of today, are not reacheable using the messaging mechanism.

ErrorManagement::ErrorType (*) (StreamI &stream);
ErrorManagement::ErrorType (*) (StructuredDataI &config);
ErrorManagement::ErrorType (*) (ReferenceContainer &container);

Parameters are encoded in a Message by adding a ConfigurationDatabase node, named Parameters, containing up to four elements, named param1, param2, param3 and param4, with the parameter values.

+Msg1 = {
   Class = Message
   Destination = "MsgRec1"
   Function = "Function1"
   Mode = "ExpectsIndirectReply"
   +Parameters = {
      Class = ConfigurationDatabase
         param1 = 2
         param2 = 3.14
   }
}

The name of the function to call is encoded in the Function message parameter.

Examples

Direct messages - no reply

The following is an example of direct message sending with no reply.

Sending of direct messages.
  1/**
  2 * @file MessageExample1.cpp
  3 * @brief Source file for class MessageExample1
  4 * @date 08/04/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class MessageExample1 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ConfigurationDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "MessageI.h"
 37#include "MessageFilter.h"
 38#include "Object.h"
 39#include "ObjectRegistryDatabase.h"
 40#include "Sleep.h"
 41#include "StandardParser.h"
 42
 43/*---------------------------------------------------------------------------*/
 44/*                           Static definitions                              */
 45/*---------------------------------------------------------------------------*/
 46namespace MARTe2Tutorial {
 47
 48/**
 49 * @brief Message filter for the MessageEx1 below.
 50 */
 51class MessageFilterEx1: public MARTe::Object, public MARTe::MessageFilter {
 52public:
 53    CLASS_REGISTER_DECLARATION()
 54
 55    /**
 56     * @brief NOOP.
 57     */
 58MessageFilterEx1    () : MARTe::Object(), MARTe::MessageFilter(true) {
 59        using namespace MARTe;
 60    }
 61
 62    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
 63        owner = MARTe::Reference();
 64    }
 65
 66    virtual ~MessageFilterEx1 () {
 67        if (GetName() != NULL) {
 68            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
 69                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 70        }
 71    }
 72
 73    void SetOwner(MARTe::Reference ownerIn) {
 74        owner = ownerIn;
 75    }
 76
 77    virtual MARTe::ErrorManagement::ErrorType ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest);
 78
 79private:
 80    MARTe::Reference owner;
 81
 82};
 83CLASS_REGISTER(MessageFilterEx1, "")
 84
 85/**
 86 * @brief A MARTe::Object class that will receive messages.
 87 */
 88class MessageEx1: public MARTe::Object, public MARTe::MessageI {
 89public:
 90    CLASS_REGISTER_DECLARATION()
 91
 92    /**
 93     * @brief Install the message filter.
 94     */
 95MessageEx1    () : MARTe::Object(), MARTe::MessageI() {
 96        using namespace MARTe;
 97        filter = ReferenceT<MessageFilterEx1>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
 98        filter->SetOwner(this);
 99        MessageI::InstallMessageFilter(filter);
100        messageReceived = false;
101    }
102
103    virtual ~MessageEx1 () {
104        if (GetName() != NULL) {
105            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
106                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
107        }
108    }
109
110    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
111        filter->SetOwner(MARTe::Reference());
112        RemoveMessageFilter(filter);
113    }
114
115    /**
116     * @brief Print the message contents in the screen.
117     */
118    MARTe::ErrorManagement::ErrorType CheckMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
119        using namespace MARTe;
120        const Object *senderObj = messageToTest->GetSender();
121        CCString sender = senderObj ? senderObj->GetName() : "anonymous";
122        CCString destination = messageToTest->GetDestination();
123        CCString function = messageToTest->GetFunction();
124        bool expectsReply = messageToTest->ExpectsReply();
125        bool expectsIndirectReply = messageToTest->ExpectsIndirectReply();
126        bool isReply = messageToTest->IsReply();
127        REPORT_ERROR(MARTe::ErrorManagement::Information, "Received message from %s to %s with function %s "
128                "(expectsReply? %d expectsIndirectReply? %d isReply? %d", sender.GetList(), destination.GetList(),
129                function.GetList(), expectsReply, expectsIndirectReply, isReply);
130
131        messageReceived = true;
132        return ErrorManagement::NoError;
133    }
134
135    bool messageReceived;
136private:
137    MARTe::ReferenceT<MessageFilterEx1> filter;
138};
139
140CLASS_REGISTER(MessageEx1, "")
141
142//Delegate to the owner the handling of the message (but could be handled by the filter itself as well).
143MARTe::ErrorManagement::ErrorType MessageFilterEx1::ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
144    MARTe::ReferenceT<MessageEx1> ownerT = owner;
145    MARTe::ErrorManagement::ErrorType err;
146    err.fatalError = !owner.IsValid();
147    if (err.ErrorsCleared()) {
148        err = ownerT->CheckMessage(messageToTest);
149    }
150    return err;
151}
152
153/**
154 * @brief A MARTe::ReferenceContainer class that will send any messages inserted into it. Note that it does not inherit from MessageI.
155 */
156class MessageEx2: public MARTe::ReferenceContainer {
157public:
158    CLASS_REGISTER_DECLARATION()
159
160    /**
161     * @brief NOOP.
162     */
163MessageEx2    () : MARTe::ReferenceContainer() {
164    }
165
166    virtual ~MessageEx2 () {
167        if (GetName() != NULL) {
168            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
169                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
170        }
171    }
172
173    void SendMessages() {
174        using namespace MARTe;
175        uint32 numberOfMessages = Size();
176        uint32 i;
177        for (i=0u; i<numberOfMessages; i++) {
178            ReferenceT<Message> msg = Get(i);
179            if (msg.IsValid()) {
180                ErrorManagement::ErrorType err = MessageI::SendMessage(msg, this);
181                REPORT_ERROR(err, "Message %s sent", msg->GetName());
182            }
183        }
184    }
185
186};
187
188CLASS_REGISTER(MessageEx2, "")
189
190}
191/*---------------------------------------------------------------------------*/
192/*                           Method definitions                              */
193/*---------------------------------------------------------------------------*/
194
195int main(int argc, char **argv) {
196    using namespace MARTe;
197    using namespace MARTe2Tutorial;
198    SetErrorProcessFunction(&ErrorProcessExampleFunction);
199
200    StreamString configurationCfg = ""
201            "+MsgRec1 = {\n"
202            "    Class = MessageEx1\n"
203            "}\n"
204            "+MsgRec2 = {\n"
205            "    Class = MessageEx1\n"
206            "}\n"
207            "+MsgRec3 = {\n"
208            "    Class = MessageEx1\n"
209            "}\n"
210            "+MsgSender1= {\n"
211            "    Class = MessageEx2\n"
212            "    +Msg1 = {\n"
213            "        Class = Message\n"
214            "        Destination = MsgRec3"
215            "        Function = \"AFunction\""
216            "    }"
217            "    +Msg2 = {\n"
218            "        Class = Message\n"
219            "        Destination = MsgRec2"
220            "        Function = \"BFunction\""
221            "    }"
222            "    +Msg3 = {\n"
223            "        Class = Message\n"
224            "        Destination = MsgRec1"
225            "        Function = \"CFunction\""
226            "    }"
227            "}";
228
229    REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
230    ConfigurationDatabase cdb;
231    StreamString err;
232    //Force the string to be seeked to the beginning.
233    configurationCfg.Seek(0LLU);
234    StandardParser parser(configurationCfg, cdb, &err);
235    bool ok = parser.Parse();
236    if (ok) {
237        //After parsing the tree is pointing at the last leaf
238        cdb.MoveToRoot();
239        ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
240    }
241    else {
242        StreamString errPrint;
243        errPrint.Printf("Failed to parse %s", err.Buffer());
244        REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
245    }
246
247    if (ok) {
248        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
249    }
250
251    ReferenceT<MessageEx1> msgRec1 = ObjectRegistryDatabase::Instance()->Find("MsgRec1");
252    ReferenceT<MessageEx1> msgRec2 = ObjectRegistryDatabase::Instance()->Find("MsgRec2");
253    ReferenceT<MessageEx1> msgRec3 = ObjectRegistryDatabase::Instance()->Find("MsgRec3");
254    ReferenceT<MessageEx2> msgSender1 = ObjectRegistryDatabase::Instance()->Find("MsgSender1");
255
256    if ((msgSender1.IsValid()) && (msgRec1.IsValid()) && (msgRec2.IsValid()) && (msgRec3.IsValid())) {
257        msgSender1->SendMessages();
258        while (!msgRec1->messageReceived) {
259            Sleep::MSec(100);
260        }
261        while (!msgRec2->messageReceived) {
262            Sleep::MSec(100);
263        }
264        while (!msgRec3->messageReceived) {
265            Sleep::MSec(100);
266        }
267    }
268    //Purge all the Objects!
269    MARTe::ObjectRegistryDatabase::Instance()->Purge();
270    return 0;
271}

Direct messages - reply

Another example of a direct message sending, but with reply.

Sending of direct messages with reply.
  1/**
  2 * @file MessageExample2.cpp
  3 * @brief Source file for class MessageExample2
  4 * @date 17/04/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class MessageExample2 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ConfigurationDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "MessageI.h"
 37#include "MessageFilter.h"
 38#include "Object.h"
 39#include "ObjectRegistryDatabase.h"
 40#include "Sleep.h"
 41#include "StandardParser.h"
 42
 43/*---------------------------------------------------------------------------*/
 44/*                           Static definitions                              */
 45/*---------------------------------------------------------------------------*/
 46namespace MARTe2Tutorial {
 47
 48/**
 49 * @brief Message filter for the MessageEx1 below (which replies to the message sent).
 50 */
 51class MessageFilterEx1: public MARTe::Object, public MARTe::MessageFilter {
 52public:
 53    CLASS_REGISTER_DECLARATION()
 54
 55    /**
 56     * @brief NOOP.
 57     */
 58MessageFilterEx1    () : MARTe::Object(), MARTe::MessageFilter(true) {
 59        using namespace MARTe;
 60    }
 61
 62    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
 63        owner = MARTe::Reference();
 64    }
 65
 66    virtual ~MessageFilterEx1 () {
 67        if (GetName() != NULL) {
 68            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
 69                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 70        }
 71    }
 72
 73    void SetOwner(MARTe::Reference ownerIn) {
 74        owner = ownerIn;
 75    }
 76
 77    virtual MARTe::ErrorManagement::ErrorType ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest);
 78
 79private:
 80    MARTe::Reference owner;
 81
 82};
 83CLASS_REGISTER(MessageFilterEx1, "")
 84
 85/**
 86 * @brief A MARTe::Object class that will receive and reply to messages.
 87 */
 88class MessageEx1: public MARTe::Object, public MARTe::MessageI {
 89public:
 90    CLASS_REGISTER_DECLARATION()
 91
 92    /**
 93     * @brief Install the message filter.
 94     */
 95MessageEx1    () : MARTe::Object(), MARTe::MessageI() {
 96        using namespace MARTe;
 97        filter = ReferenceT<MessageFilterEx1>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
 98        filter->SetOwner(this);
 99        MessageI::InstallMessageFilter(filter);
100        messageReceived = false;
101    }
102
103    virtual ~MessageEx1 () {
104        if (GetName() != NULL) {
105            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
106                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
107        }
108    }
109
110    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
111        filter->SetOwner(MARTe::Reference());
112        RemoveMessageFilter(filter);
113    }
114
115    /**
116     * @brief Print the message contents in the screen.
117     */
118    MARTe::ErrorManagement::ErrorType CheckMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
119        using namespace MARTe;
120        const Object *senderObj = messageToTest->GetSender();
121        CCString sender = senderObj ? senderObj->GetName() : "anonymous";
122        CCString destination = messageToTest->GetDestination();
123        CCString function = messageToTest->GetFunction();
124        bool expectsReply = messageToTest->ExpectsReply();
125        bool expectsIndirectReply = messageToTest->ExpectsIndirectReply();
126        bool isReply = messageToTest->IsReply();
127        REPORT_ERROR(MARTe::ErrorManagement::Information, "Received message from %s to %s with function %s "
128                "(expectsReply? %d expectsIndirectReply? %d isReply? %d", sender.GetList(), destination.GetList(),
129                function.GetList(), expectsReply, expectsIndirectReply, isReply);
130
131        messageReceived = true;
132        return ErrorManagement::NoError;
133    }
134
135    bool messageReceived;
136private:
137    MARTe::ReferenceT<MessageFilterEx1> filter;
138};
139
140CLASS_REGISTER(MessageEx1, "")
141
142//Delegate to the owner the handling of the message (but could be handled by the filter itself as well).
143MARTe::ErrorManagement::ErrorType MessageFilterEx1::ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
144    using namespace MARTe;
145    ReferenceT<MessageEx1> ownerT = owner;
146    ErrorManagement::ErrorType err;
147    err.fatalError = !owner.IsValid();
148    if (err.ErrorsCleared()) {
149        err = ownerT->CheckMessage(messageToTest);
150    }
151    //Mark the message as a (direct) reply
152    if (err.ErrorsCleared()) {
153        messageToTest->SetAsReply(true);
154        //And insert an (example) object into
155        ReferenceT<Object> example = ReferenceT<Object>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
156        example->SetName("REPLY");
157        messageToTest->Insert(example);
158    }
159    return err;
160}
161
162/**
163 * @brief A MARTe::ReferenceContainer class that will send any messages inserted into it.
164 * Note that it does not inherit from MessageI.
165 */
166class MessageEx2: public MARTe::ReferenceContainer {
167public:
168    CLASS_REGISTER_DECLARATION()
169
170    /**
171     * @brief NOOP.
172     */
173MessageEx2    () : MARTe::ReferenceContainer() {
174        replyReceived = false;
175    }
176
177    virtual ~MessageEx2 () {
178        if (GetName() != NULL) {
179            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
180                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
181        }
182    }
183
184    void SendMessages() {
185        using namespace MARTe;
186        uint32 numberOfMessages = Size();
187        uint32 i;
188        for (i=0u; i<numberOfMessages; i++) {
189            ReferenceT<Message> msg = Get(i);
190            ErrorManagement::ErrorType err;
191            err.fatalError = !msg.IsValid();
192            if (err.ErrorsCleared()) {
193                err = MessageI::SendMessageAndWaitReply(msg, this);
194                REPORT_ERROR(err, "Message %s sent", msg->GetName());
195            }
196            if (err.ErrorsCleared()) {
197                if (msg->IsReply()) {
198                    REPORT_ERROR(err, "Message %s is now a reply as expected", msg->GetName());
199                }
200                if (msg->Size() > 0) {
201                    Reference ref = msg->Get(0);
202                    REPORT_ERROR(err, "Message %s contains an object in the reply with name %s", msg->GetName(), ref->GetName());
203                }
204            }
205        }
206        replyReceived = true;
207    }
208
209    bool replyReceived;
210};
211
212CLASS_REGISTER(MessageEx2, "")
213
214}
215/*---------------------------------------------------------------------------*/
216/*                           Method definitions                              */
217/*---------------------------------------------------------------------------*/
218
219int main(int argc, char **argv) {
220    using namespace MARTe;
221    using namespace MARTe2Tutorial;
222    SetErrorProcessFunction(&ErrorProcessExampleFunction);
223
224    StreamString configurationCfg = ""
225            "+MsgRec1 = {\n"
226            "    Class = MessageEx1\n"
227            "}\n"
228            "+MsgRec2 = {\n"
229            "    Class = MessageEx1\n"
230            "}\n"
231            "+MsgRec3 = {\n"
232            "    Class = MessageEx1\n"
233            "}\n"
234            "+MsgSender1= {\n"
235            "    Class = MessageEx2\n"
236            "    +Msg1 = {\n"
237            "        Class = Message\n"
238            "        Destination = MsgRec3"
239            "        Function = \"AFunction\""
240            "    }"
241            "    +Msg2 = {\n"
242            "        Class = Message\n"
243            "        Destination = MsgRec2"
244            "        Function = \"BFunction\""
245            "    }"
246            "    +Msg3 = {\n"
247            "        Class = Message\n"
248            "        Destination = MsgRec1"
249            "        Function = \"CFunction\""
250            "    }"
251            "}";
252
253    REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
254    ConfigurationDatabase cdb;
255    StreamString err;
256    //Force the string to be seeked to the beginning.
257    configurationCfg.Seek(0LLU);
258    StandardParser parser(configurationCfg, cdb, &err);
259    bool ok = parser.Parse();
260    if (ok) {
261        //After parsing the tree is pointing at the last leaf
262        cdb.MoveToRoot();
263        ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
264    }
265    else {
266        StreamString errPrint;
267        errPrint.Printf("Failed to parse %s", err.Buffer());
268        REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
269    }
270
271    if (ok) {
272        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
273    }
274
275    ReferenceT<MessageEx1> msgRec1 = ObjectRegistryDatabase::Instance()->Find("MsgRec1");
276    ReferenceT<MessageEx1> msgRec2 = ObjectRegistryDatabase::Instance()->Find("MsgRec2");
277    ReferenceT<MessageEx1> msgRec3 = ObjectRegistryDatabase::Instance()->Find("MsgRec3");
278    ReferenceT<MessageEx2> msgSender1 = ObjectRegistryDatabase::Instance()->Find("MsgSender1");
279
280    if ((msgSender1.IsValid()) && (msgRec1.IsValid()) && (msgRec2.IsValid()) && (msgRec3.IsValid())) {
281        msgSender1->SendMessages();
282        while (!msgRec1->messageReceived) {
283            Sleep::MSec(100);
284        }
285        while (!msgRec2->messageReceived) {
286            Sleep::MSec(100);
287        }
288        while (!msgRec3->messageReceived) {
289            Sleep::MSec(100);
290        }
291        while (!msgSender1->replyReceived) {
292            Sleep::MSec(100);
293        }
294    }
295    //Purge all the Objects!
296    MARTe::ObjectRegistryDatabase::Instance()->Purge();
297    return 0;
298}

Indirect messages - reply

An example of an indirect message sending with reply.

Sending of indirect messages with reply.
  1/**
  2 * @file MessageExample3.cpp
  3 * @brief Source file for class MessageExample3
  4 * @date 17/04/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class MessageExample3 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ConfigurationDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "MessageI.h"
 37#include "MessageFilter.h"
 38#include "Object.h"
 39#include "ObjectRegistryDatabase.h"
 40#include "ReplyMessageCatcherMessageFilter.h"
 41#include "Sleep.h"
 42#include "StandardParser.h"
 43
 44/*---------------------------------------------------------------------------*/
 45/*                           Static definitions                              */
 46/*---------------------------------------------------------------------------*/
 47namespace MARTe2Tutorial {
 48
 49/**
 50 * @brief Message filter for the MessageEx1 below (which replies to the message sent).
 51 */
 52class MessageFilterEx1: public MARTe::Object, public MARTe::MessageFilter {
 53public:
 54    CLASS_REGISTER_DECLARATION()
 55
 56    /**
 57     * @brief NOOP.
 58     */
 59MessageFilterEx1    () : MARTe::Object(), MARTe::MessageFilter(true) {
 60        using namespace MARTe;
 61    }
 62
 63    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
 64        owner = MARTe::Reference();
 65    }
 66
 67    virtual ~MessageFilterEx1 () {
 68        if (GetName() != NULL) {
 69            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
 70                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 71        }
 72    }
 73
 74    void SetOwner(MARTe::Reference ownerIn) {
 75        owner = ownerIn;
 76    }
 77
 78    virtual MARTe::ErrorManagement::ErrorType ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest);
 79
 80private:
 81    MARTe::Reference owner;
 82
 83};
 84CLASS_REGISTER(MessageFilterEx1, "")
 85
 86/**
 87 * @brief A MARTe::Object class that will receive and reply to messages.
 88 */
 89class MessageEx1: public MARTe::Object, public MARTe::MessageI {
 90public:
 91    CLASS_REGISTER_DECLARATION()
 92
 93    /**
 94     * @brief Install the message filter.
 95     */
 96MessageEx1    () : MARTe::Object(), MARTe::MessageI() {
 97        using namespace MARTe;
 98        filter = ReferenceT<MessageFilterEx1>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
 99        filter->SetOwner(this);
100        MessageI::InstallMessageFilter(filter);
101        messageReceived = false;
102    }
103
104    virtual ~MessageEx1 () {
105        if (GetName() != NULL) {
106            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
107                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
108        }
109    }
110
111    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
112        filter->SetOwner(MARTe::Reference());
113        RemoveMessageFilter(filter);
114    }
115
116    /**
117     * @brief Print the message contents in the screen.
118     */
119    MARTe::ErrorManagement::ErrorType CheckMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
120        using namespace MARTe;
121        const Object *senderObj = messageToTest->GetSender();
122        CCString sender = senderObj ? senderObj->GetName() : "anonymous";
123        CCString destination = messageToTest->GetDestination();
124        CCString function = messageToTest->GetFunction();
125        bool expectsReply = messageToTest->ExpectsReply();
126        bool expectsIndirectReply = messageToTest->ExpectsIndirectReply();
127        bool isReply = messageToTest->IsReply();
128        REPORT_ERROR(MARTe::ErrorManagement::Information, "Received message from %s to %s with function %s "
129                "(expectsReply? %d expectsIndirectReply? %d isReply? %d", sender.GetList(), destination.GetList(),
130                function.GetList(), expectsReply, expectsIndirectReply, isReply);
131
132        messageReceived = true;
133        return ErrorManagement::NoError;
134    }
135
136    bool messageReceived;
137private:
138    MARTe::ReferenceT<MessageFilterEx1> filter;
139};
140
141CLASS_REGISTER(MessageEx1, "")
142
143//Delegate to the owner the handling of the message (but could be handled by the filter itself as well).
144MARTe::ErrorManagement::ErrorType MessageFilterEx1::ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
145    using namespace MARTe;
146    ReferenceT<MessageEx1> ownerT = owner;
147    ErrorManagement::ErrorType err;
148    err.fatalError = !owner.IsValid();
149    if (err.ErrorsCleared()) {
150        err = ownerT->CheckMessage(messageToTest);
151    }
152    //Mark the message as a (direct) reply
153    if (err.ErrorsCleared()) {
154        messageToTest->SetAsReply(true);
155        //And insert an (example) object into
156        ReferenceT<Object> example = ReferenceT<Object>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
157        example->SetName("REPLY");
158        messageToTest->Insert(example);
159        if (messageToTest->ExpectsIndirectReply()) {
160            //Indirect reply... resend the message
161            err = MessageI::SendMessage(messageToTest, this);
162        }
163    }
164    return err;
165}
166
167/**
168 * @brief A MARTe::Object class that will send indirect reply messages and waits for the reply.
169 * Note that the method SendMessageAndWaitIndirectReply will automatically register a ReplyMessageCatcherMessageFilter filter
170 */
171class MessageEx2: public MARTe::ReferenceContainer, public MARTe::MessageI {
172public:
173    CLASS_REGISTER_DECLARATION()
174
175    /**
176     * @brief NOOP
177     */
178    MessageEx2 () : MARTe::ReferenceContainer(), MARTe::MessageI() {
179        using namespace MARTe;
180        replyReceived = false;
181    }
182
183    virtual ~MessageEx2 () {
184        if (GetName() != NULL) {
185            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
186                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
187        }
188    }
189
190    void SendMessages() {
191        using namespace MARTe;
192        uint32 numberOfMessages = Size();
193        uint32 i;
194        for (i=0u; i<numberOfMessages; i++) {
195            ReferenceT<Message> msg = Get(i);
196            ErrorManagement::ErrorType err;
197            err.fatalError = !msg.IsValid();
198            if (err.ErrorsCleared()) {
199                if (!msg->ExpectsIndirectReply()) {
200                    msg->SetExpectsIndirectReply(true);
201                }
202                err = SendMessageAndWaitIndirectReply(msg);
203                REPORT_ERROR(err, "Message %s sent", msg->GetName());
204            }
205            if (err.ErrorsCleared()) {
206                if (msg->IsReply()) {
207                    REPORT_ERROR(err, "Message %s is now a reply as expected", msg->GetName());
208                }
209                if (msg->Size() > 0) {
210                    Reference ref = msg->Get(0);
211                    REPORT_ERROR(err, "Message %s contains an object in the reply with name %s", msg->GetName(), ref->GetName());
212                }
213            }
214        }
215        replyReceived = true;
216    }
217
218    bool replyReceived;
219};
220
221CLASS_REGISTER(MessageEx2, "")
222
223}
224/*---------------------------------------------------------------------------*/
225/*                           Method definitions                              */
226/*---------------------------------------------------------------------------*/
227
228int main(int argc, char **argv) {
229    using namespace MARTe;
230    using namespace MARTe2Tutorial;
231    SetErrorProcessFunction(&ErrorProcessExampleFunction);
232
233    StreamString configurationCfg = ""
234            "+MsgRec1 = {\n"
235            "    Class = MessageEx1\n"
236            "}\n"
237            "+MsgRec2 = {\n"
238            "    Class = MessageEx1\n"
239            "}\n"
240            "+MsgRec3 = {\n"
241            "    Class = MessageEx1\n"
242            "}\n"
243            "+MsgSender1= {\n"
244            "    Class = MessageEx2\n"
245            "    +Msg1 = {\n"
246            "        Class = Message\n"
247            "        Destination = MsgRec3"
248            "        Function = \"AFunction\""
249            "        Mode = \"ExpectsIndirectReply\""
250            "    }"
251            "    +Msg2 = {\n"
252            "        Class = Message\n"
253            "        Destination = MsgRec2"
254            "        Function = \"BFunction\""
255            "        Mode = \"ExpectsIndirectReply\""
256            "    }"
257            "    +Msg3 = {\n"
258            "        Class = Message\n"
259            "        Destination = MsgRec1"
260            "        Function = \"CFunction\""
261            "        Mode = \"ExpectsIndirectReply\""
262            "    }"
263            "}";
264
265    REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
266    ConfigurationDatabase cdb;
267    StreamString err;
268    //Force the string to be seeked to the beginning.
269    configurationCfg.Seek(0LLU);
270    StandardParser parser(configurationCfg, cdb, &err);
271    bool ok = parser.Parse();
272    if (ok) {
273        //After parsing the tree is pointing at the last leaf
274        cdb.MoveToRoot();
275        ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
276    }
277    else {
278        StreamString errPrint;
279        errPrint.Printf("Failed to parse %s", err.Buffer());
280        REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
281    }
282
283    if (ok) {
284        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
285    }
286
287    ReferenceT<MessageEx1> msgRec1 = ObjectRegistryDatabase::Instance()->Find("MsgRec1");
288    ReferenceT<MessageEx1> msgRec2 = ObjectRegistryDatabase::Instance()->Find("MsgRec2");
289    ReferenceT<MessageEx1> msgRec3 = ObjectRegistryDatabase::Instance()->Find("MsgRec3");
290    ReferenceT<MessageEx2> msgSender1 = ObjectRegistryDatabase::Instance()->Find("MsgSender1");
291
292    if ((msgSender1.IsValid()) && (msgRec1.IsValid()) && (msgRec2.IsValid()) && (msgRec3.IsValid())) {
293        msgSender1->SendMessages();
294        while (!msgRec1->messageReceived) {
295            Sleep::MSec(100);
296        }
297        while (!msgRec2->messageReceived) {
298            Sleep::MSec(100);
299        }
300        while (!msgRec3->messageReceived) {
301            Sleep::MSec(100);
302        }
303        while (!msgSender1->replyReceived) {
304            Sleep::MSec(100);
305        }
306    }
307    //Purge all the Objects!
308    MARTe::ObjectRegistryDatabase::Instance()->Purge();
309    return 0;
310}

Queued messages

The following is an example of indirect messages handled in the context of a queue and of a different thread. The replies are also handled in the context of a different thread.

Queued messages (note the usage of the QueuedMessageI).
  1/**
  2 * @file MessageExample4.cpp
  3 * @brief Source file for class MessageExample4
  4 * @date 17/04/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class MessageExample4 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ConfigurationDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "MessageI.h"
 37#include "MessageFilter.h"
 38#include "Object.h"
 39#include "ObjectRegistryDatabase.h"
 40#include "QueuedMessageI.h"
 41#include "QueuedReplyMessageCatcherFilter.h"
 42#include "Sleep.h"
 43#include "StandardParser.h"
 44
 45/*---------------------------------------------------------------------------*/
 46/*                           Static definitions                              */
 47/*---------------------------------------------------------------------------*/
 48namespace MARTe2Tutorial {
 49
 50/**
 51 * @brief Message filter for the MessageEx1 below (which replies to the message sent).
 52 */
 53class MessageFilterEx1: public MARTe::Object, public MARTe::MessageFilter {
 54public:
 55    CLASS_REGISTER_DECLARATION()
 56
 57    /**
 58     * @brief NOOP.
 59     */
 60    MessageFilterEx1 () : MARTe::Object(), MARTe::MessageFilter(true) {
 61        using namespace MARTe;
 62    }
 63
 64    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
 65        owner = MARTe::Reference();
 66    }
 67
 68    virtual ~MessageFilterEx1 () {
 69        if (GetName() != NULL) {
 70            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
 71                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 72        }
 73    }
 74
 75    void SetOwner(MARTe::Reference ownerIn) {
 76        owner = ownerIn;
 77    }
 78
 79    virtual MARTe::ErrorManagement::ErrorType ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest);
 80
 81private:
 82    MARTe::Reference owner;
 83
 84};
 85CLASS_REGISTER(MessageFilterEx1, "")
 86
 87/**
 88 * @brief A MARTe::Object class that will receive and reply to messages.
 89 */
 90class MessageEx1: public MARTe::Object, public MARTe::QueuedMessageI {
 91public:
 92    CLASS_REGISTER_DECLARATION()
 93
 94    /**
 95     * @brief Install the message filter.
 96     */
 97MessageEx1    () : MARTe::Object(), MARTe::QueuedMessageI() {
 98        using namespace MARTe;
 99        filter = ReferenceT<MessageFilterEx1>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
100        filter->SetOwner(this);
101        QueuedMessageI::InstallMessageFilter(filter);
102        messageReceived = false;
103    }
104
105    virtual ~MessageEx1 () {
106        if (GetName() != NULL) {
107            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
108                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
109        }
110    }
111
112    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
113        filter->SetOwner(MARTe::Reference());
114        RemoveMessageFilter(filter);
115    }
116
117    /**
118     * @brief Print the message contents in the screen.
119     */
120    MARTe::ErrorManagement::ErrorType CheckMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
121        using namespace MARTe;
122        const Object *senderObj = messageToTest->GetSender();
123        CCString sender = senderObj ? senderObj->GetName() : "anonymous";
124        CCString destination = messageToTest->GetDestination();
125        CCString function = messageToTest->GetFunction();
126        bool expectsReply = messageToTest->ExpectsReply();
127        bool expectsIndirectReply = messageToTest->ExpectsIndirectReply();
128        bool isReply = messageToTest->IsReply();
129        REPORT_ERROR(MARTe::ErrorManagement::Information, "Received message from %s to %s with function %s "
130                "(expectsReply? %d expectsIndirectReply? %d isReply? %d", sender.GetList(), destination.GetList(),
131                function.GetList(), expectsReply, expectsIndirectReply, isReply);
132
133        messageReceived = true;
134        return ErrorManagement::NoError;
135    }
136
137    bool messageReceived;
138private:
139    MARTe::ReferenceT<MessageFilterEx1> filter;
140};
141
142CLASS_REGISTER(MessageEx1, "")
143
144//Delegate to the owner the handling of the message (but could be handled by the filter itself as well).
145MARTe::ErrorManagement::ErrorType MessageFilterEx1::ConsumeMessage(MARTe::ReferenceT<MARTe::Message> &messageToTest) {
146    using namespace MARTe;
147    ReferenceT<MessageEx1> ownerT = owner;
148    ErrorManagement::ErrorType err;
149    err.fatalError = !owner.IsValid();
150    if (err.ErrorsCleared()) {
151        err = ownerT->CheckMessage(messageToTest);
152    }
153    //Mark the message as a (direct) reply
154    if (err.ErrorsCleared()) {
155        messageToTest->SetAsReply(true);
156        //And insert an (example) object into
157        ReferenceT<Object> example = ReferenceT<Object>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
158        example->SetName("REPLY");
159        messageToTest->Insert(example);
160        if (messageToTest->ExpectsIndirectReply()) {
161            //Indirect reply... resends the message
162            err = MessageI::SendMessage(messageToTest, this);
163        }
164    }
165    return err;
166}
167
168/**
169 * @brief A MARTe::Object class that will send indirect reply messages and wait for the reply also using a queue.
170 */
171class MessageEx2: public MARTe::ReferenceContainer, public MARTe::MessageI {
172public:
173    CLASS_REGISTER_DECLARATION()
174
175    /**
176     * @brief NOOP
177     */
178MessageEx2    () : MARTe::ReferenceContainer(), MARTe::MessageI() {
179        using namespace MARTe;
180        replyReceived = false;
181    }
182
183    virtual ~MessageEx2 () {
184        if (GetName() != NULL) {
185            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
186                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
187        }
188    }
189
190    void SendMessages() {
191        using namespace MARTe;
192        ErrorManagement::ErrorType err;
193        //Semaphore to wait for replies
194        EventSem waitSem;
195        bool ok = waitSem.Create();
196        if (ok) {
197            ok = waitSem.Reset();
198        }
199
200        //Prepare to wait for eventual replies
201        ReferenceContainer eventReplyContainer;
202        uint32 i;
203
204        //Only accept indirect replies
205        for (i = 0u; i < Size(); i++) {
206            ReferenceT<Message> eventMsg = Get(i);
207            if (eventMsg.IsValid()) {
208                if (eventMsg->ExpectsReply()) {
209                    eventMsg->SetExpectsIndirectReply(true);
210                }
211                if (eventMsg->ExpectsIndirectReply()) {
212                    err = !eventReplyContainer.Insert(eventMsg);
213                }
214            }
215        }
216
217        if (ok) {
218            ok = err.ErrorsCleared();
219        }
220        //Prepare the filter which will wait for all the replies
221        if ((eventReplyContainer.Size() > 0u) && (ok)) {
222            ReferenceT<QueuedReplyMessageCatcherFilter> filter(new (NULL) QueuedReplyMessageCatcherFilter());
223            filter->SetMessagesToCatch(eventReplyContainer);
224            filter->SetEventSemaphore(waitSem);
225            err = MessageI::InstallMessageFilter(filter, 0);
226        }
227
228        ok = err.ErrorsCleared();
229        for (i = 0u; (i < Size()) && (ok); i++) {
230            ReferenceT<Message> msg = Get(i);
231            if (msg.IsValid()) {
232                msg->SetAsReply(false);
233                err = MessageI::SendMessage(msg, this);
234            }
235            ok = err.ErrorsCleared();
236        }
237        //Wait for all the replies to arrive...
238        if (ok) {
239            if (eventReplyContainer.Size() > 0u) {
240                err = waitSem.Wait(TTInfiniteWait);
241            }
242            ok = err.ErrorsCleared();
243
244        }
245        for (i = 0u; (i < Size()) && (ok); i++) {
246            ReferenceT<Message> msg = Get(i);
247            if (msg->IsReply()) {
248                REPORT_ERROR(err, "Message %s is now a reply as expected", msg->GetName());
249            }
250            if (msg->Size() > 0) {
251                Reference ref = msg->Get(0);
252                REPORT_ERROR(err, "Message %s contains an object in the reply with name %s", msg->GetName(), ref->GetName());
253            }
254        }
255        replyReceived = true;
256    }
257
258    bool replyReceived;
259};
260
261CLASS_REGISTER(MessageEx2, "")
262
263}
264/*---------------------------------------------------------------------------*/
265/*                           Method definitions                              */
266/*---------------------------------------------------------------------------*/
267
268int main(int argc, char **argv) {
269    using namespace MARTe;
270    using namespace MARTe2Tutorial;
271    SetErrorProcessFunction(&ErrorProcessExampleFunction);
272
273    StreamString configurationCfg = ""
274            "+MsgRec1 = {\n"
275            "    Class = MessageEx1\n"
276            "}\n"
277            "+MsgRec2 = {\n"
278            "    Class = MessageEx1\n"
279            "}\n"
280            "+MsgRec3 = {\n"
281            "    Class = MessageEx1\n"
282            "}\n"
283            "+MsgSender1= {\n"
284            "    Class = MessageEx2\n"
285            "    +Msg1 = {\n"
286            "        Class = Message\n"
287            "        Destination = MsgRec3"
288            "        Function = \"AFunction\""
289            "        Mode = \"ExpectsIndirectReply\""
290            "    }"
291            "    +Msg2 = {\n"
292            "        Class = Message\n"
293            "        Destination = MsgRec2"
294            "        Function = \"BFunction\""
295            "        Mode = \"ExpectsIndirectReply\""
296            "    }"
297            "    +Msg3 = {\n"
298            "        Class = Message\n"
299            "        Destination = MsgRec1"
300            "        Function = \"CFunction\""
301            "        Mode = \"ExpectsIndirectReply\""
302            "    }"
303            "}";
304
305    REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
306    ConfigurationDatabase cdb;
307    StreamString err;
308    //Force the string to be seeked to the beginning.
309    configurationCfg.Seek(0LLU);
310    StandardParser parser(configurationCfg, cdb, &err);
311    bool ok = parser.Parse();
312    if (ok) {
313        //After parsing the tree is pointing at the last leaf
314        cdb.MoveToRoot();
315        ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
316    }
317    else {
318        StreamString errPrint;
319        errPrint.Printf("Failed to parse %s", err.Buffer());
320        REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
321    }
322
323    if (ok) {
324        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
325    }
326
327    ReferenceT<MessageEx1> msgRec1 = ObjectRegistryDatabase::Instance()->Find("MsgRec1");
328    ReferenceT<MessageEx1> msgRec2 = ObjectRegistryDatabase::Instance()->Find("MsgRec2");
329    ReferenceT<MessageEx1> msgRec3 = ObjectRegistryDatabase::Instance()->Find("MsgRec3");
330    ReferenceT<MessageEx2> msgSender1 = ObjectRegistryDatabase::Instance()->Find("MsgSender1");
331
332    if ((msgSender1.IsValid()) && (msgRec1.IsValid()) && (msgRec2.IsValid()) && (msgRec3.IsValid())) {
333        msgRec1->Start();
334        msgRec2->Start();
335        msgRec3->Start();
336        msgSender1->SendMessages();
337        while (!msgRec1->messageReceived) {
338            Sleep::MSec(100);
339        }
340        while (!msgRec2->messageReceived) {
341            Sleep::MSec(100);
342        }
343        while (!msgRec3->messageReceived) {
344            Sleep::MSec(100);
345        }
346        while (!msgSender1->replyReceived) {
347            Sleep::MSec(100);
348        }
349        msgRec1->Stop();
350        msgRec2->Stop();
351        msgRec3->Stop();
352    }
353    //Purge all the Objects!
354    MARTe::ObjectRegistryDatabase::Instance()->Purge();
355    return 0;
356}

Remote function calls

The following is an example of remote function calls using messages.

Remote functions calling using messages.
  1/**
  2 * @file MessageExample5.cpp
  3 * @brief Source file for class MessageExample5
  4 * @date 17/04/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class MessageExample5 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "CLASSMETHODREGISTER.h"
 35#include "ConfigurationDatabase.h"
 36#include "ErrorLoggerExample.h"
 37#include "MessageI.h"
 38#include "MessageFilter.h"
 39#include "Object.h"
 40#include "ObjectRegistryDatabase.h"
 41#include "RegisteredMethodsMessageFilter.h"
 42#include "Sleep.h"
 43#include "StandardParser.h"
 44
 45/*---------------------------------------------------------------------------*/
 46/*                           Static definitions                              */
 47/*---------------------------------------------------------------------------*/
 48namespace MARTe2Tutorial {
 49
 50/**
 51 * @brief A MARTe::Object class that registers a set of RPC functions that can be called
 52 * with messages.
 53 */
 54class MessageEx1: public MARTe::Object, public MARTe::MessageI {
 55public:
 56    CLASS_REGISTER_DECLARATION()
 57
 58    /**
 59     * @brief Install the RegisteredMethodsMessageFilter filter.
 60     */
 61    MessageEx1 () : MARTe::Object(), MARTe::MessageI() {
 62        using namespace MARTe;
 63        filter = ReferenceT<RegisteredMethodsMessageFilter>(GlobalObjectsDatabase::Instance()->GetStandardHeap());
 64        filter->SetDestination(this);
 65        MessageI::InstallMessageFilter(filter);
 66    }
 67
 68    virtual ~MessageEx1 () {
 69        if (GetName() != NULL) {
 70            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
 71                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 72        }
 73    }
 74
 75    virtual void Purge(MARTe::ReferenceContainer &purgeList) {
 76        RemoveMessageFilter(filter);
 77    }
 78
 79    MARTe::ErrorManagement::ErrorType Function0 () {
 80        REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "Function0 called.");
 81        return MARTe::ErrorManagement::NoError;
 82    }
 83
 84    MARTe::ErrorManagement::ErrorType Function1 (MARTe::uint32 a, MARTe::float32 b) {
 85        REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "Received %u %f.", a, b);
 86        return MARTe::ErrorManagement::NoError;
 87    }
 88
 89    MARTe::ErrorManagement::ErrorType Function2 (MARTe::int32 &a, MARTe::float32 &b) {
 90        REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "Received %u %f.", a, b);
 91        a = -a;
 92        b = -b;
 93        return MARTe::ErrorManagement::NoError;
 94    }
 95
 96    MARTe::ErrorManagement::ErrorType Function3 (MARTe::StreamString a) {
 97        REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "Received %s.", a.Buffer());
 98        return MARTe::ErrorManagement::NoError;
 99    }
100
101private:
102    MARTe::ReferenceT<MARTe::RegisteredMethodsMessageFilter> filter;
103};
104
105CLASS_REGISTER(MessageEx1, "")
106CLASS_METHOD_REGISTER(MessageEx1, Function0)
107CLASS_METHOD_REGISTER(MessageEx1, Function1)
108CLASS_METHOD_REGISTER(MessageEx1, Function2)
109CLASS_METHOD_REGISTER(MessageEx1, Function3)
110
111/**
112 * @brief A MARTe::Object class that will send indirect reply messages and waits for the reply.
113 * Note that the method SendMessageAndWaitIndirectReply will automatically register a ReplyMessageCatcherMessageFilter filter
114 */
115class MessageEx2: public MARTe::ReferenceContainer, public MARTe::MessageI {
116public:
117    CLASS_REGISTER_DECLARATION()
118
119    /**
120     * @brief NOOP
121     */
122    MessageEx2 () : MARTe::ReferenceContainer(), MARTe::MessageI() {
123        using namespace MARTe;
124        replyReceived = false;
125    }
126
127    virtual ~MessageEx2 () {
128        if (GetName() != NULL) {
129            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
130                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
131        }
132    }
133
134    void SendMessages() {
135        using namespace MARTe;
136        uint32 numberOfMessages = Size();
137        uint32 i;
138        for (i=0u; i<numberOfMessages; i++) {
139            ReferenceT<Message> msg = Get(i);
140            ErrorManagement::ErrorType err;
141            err.fatalError = !msg.IsValid();
142            if (err.ErrorsCleared()) {
143                if (!msg->ExpectsIndirectReply()) {
144                    msg->SetExpectsIndirectReply(true);
145                }
146                err = SendMessageAndWaitIndirectReply(msg);
147                REPORT_ERROR(err, "Message %s sent", msg->GetName());
148            }
149            if (err.ErrorsCleared()) {
150                if (msg->IsReply()) {
151                    REPORT_ERROR(err, "Message %s is now a reply as expected", msg->GetName());
152                    ReferenceT<ConfigurationDatabase> params;
153                    if (msg->Size() > 0) {
154                        params = msg->Get(0);
155                    }
156                    if (params.IsValid()) {
157                        REPORT_ERROR(err, "Replied parameters %!", *(params.operator ->()));
158                    }
159                }
160            }
161        }
162        replyReceived = true;
163    }
164
165    bool replyReceived;
166};
167
168CLASS_REGISTER(MessageEx2, "")
169
170}
171/*---------------------------------------------------------------------------*/
172/*                           Method definitions                              */
173/*---------------------------------------------------------------------------*/
174
175int main(int argc, char **argv) {
176    using namespace MARTe;
177    using namespace MARTe2Tutorial;
178    SetErrorProcessFunction(&ErrorProcessExampleFunction);
179
180    StreamString configurationCfg = ""
181            "+MsgRec1 = {\n"
182            "    Class = MessageEx1\n"
183            "}\n"
184            "+MsgSender1= {\n"
185            "    Class = MessageEx2\n"
186            "    +Msg0 = {\n"
187            "        Class = Message\n"
188            "        Destination = MsgRec1"
189            "        Function = \"Function0\""
190            "        Mode = \"ExpectsIndirectReply\""
191            "    }"
192            "    +Msg1 = {\n"
193            "        Class = Message\n"
194            "        Destination = MsgRec1"
195            "        Function = \"Function1\""
196            "        Mode = \"ExpectsIndirectReply\""
197            "        +Parameters = {"
198            "            Class = ConfigurationDatabase"
199            "            param1 = 2"
200            "            param2 = 3.14"
201            "        }"
202            "    }"
203            "    +Msg2 = {\n"
204            "        Class = Message\n"
205            "        Destination = MsgRec1"
206            "        Function = \"Function2\""
207            "        Mode = \"ExpectsIndirectReply\""
208            "        +Parameters = {"
209            "            Class = ConfigurationDatabase"
210            "            param1 = 2"
211            "            param2 = 3.14"
212            "        }"
213            "    }"
214            "    +Msg3 = {\n"
215            "        Class = Message\n"
216            "        Destination = MsgRec1"
217            "        Function = \"Function3\""
218            "        Mode = \"ExpectsIndirectReply\""
219            "        +Parameters = {"
220            "            Class = ConfigurationDatabase"
221            "            param1 = \"This is a string\""
222            "        }"
223            "    }"
224            "}";
225
226    REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
227    ConfigurationDatabase cdb;
228    StreamString err;
229    //Force the string to be seeked to the beginning.
230    configurationCfg.Seek(0LLU);
231    StandardParser parser(configurationCfg, cdb, &err);
232    bool ok = parser.Parse();
233    if (ok) {
234        //After parsing the tree is pointing at the last leaf
235        cdb.MoveToRoot();
236        ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
237    }
238    else {
239        StreamString errPrint;
240        errPrint.Printf("Failed to parse %s", err.Buffer());
241        REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
242    }
243
244    if (ok) {
245        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
246    }
247
248    ReferenceT<MessageEx1> msgRec1 = ObjectRegistryDatabase::Instance()->Find("MsgRec1");
249    ReferenceT<MessageEx2> msgSender1 = ObjectRegistryDatabase::Instance()->Find("MsgSender1");
250
251    if ((msgSender1.IsValid()) && (msgRec1.IsValid())) {
252        msgSender1->SendMessages();
253
254        while (!msgSender1->replyReceived) {
255            Sleep::MSec(100);
256        }
257    }
258    //Purge all the Objects!
259    MARTe::ObjectRegistryDatabase::Instance()->Purge();
260    return 0;
261}

Configuration management

The following is an example of how to update the framework configuration in runtime.

Change of configuration using messages.
  1/**
  2 * @file MessageExample6.cpp
  3 * @brief Source file for class MessageExample6
  4 * @date 17/04/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class MessageExample6 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29#include <stdio.h>
 30
 31/*---------------------------------------------------------------------------*/
 32/*                         Project header includes                           */
 33/*---------------------------------------------------------------------------*/
 34#include "AdvancedErrorManagement.h"
 35#include "CLASSMETHODREGISTER.h"
 36#include "ConfigurationDatabase.h"
 37#include "ErrorLoggerExample.h"
 38#include "MessageI.h"
 39#include "MessageFilter.h"
 40#include "Object.h"
 41#include "ObjectRegistryDatabase.h"
 42#include "RegisteredMethodsMessageFilter.h"
 43#include "Sleep.h"
 44#include "StandardParser.h"
 45
 46/*---------------------------------------------------------------------------*/
 47/*                           Static definitions                              */
 48/*---------------------------------------------------------------------------*/
 49namespace MARTe2Tutorial {
 50
 51void DumpObjectRegistryDatabase(MARTe::ReferenceContainer &rc, MARTe::uint32 depth) {
 52    MARTe::uint32 i;
 53    for (i = 0u; i < depth; i++) {
 54        printf("    ");
 55    }
 56    for (i = 0u; i < rc.Size(); i++) {
 57        MARTe::ReferenceT<MARTe::Object> rco = rc.Get(i);
 58        if (rco.IsValid()) {
 59            printf("[%s]\n", rco->GetName());
 60        }
 61        MARTe::ReferenceT<MARTe::ReferenceContainer> rcn = rc.Get(i);
 62        if (rcn.IsValid()) {
 63            DumpObjectRegistryDatabase(*rcn.operator ->(), depth + 1);
 64        }
 65    }
 66    printf("\n");
 67}
 68}
 69/*---------------------------------------------------------------------------*/
 70/*                           Method definitions                              */
 71/*---------------------------------------------------------------------------*/
 72
 73int main(int argc, char **argv) {
 74    using namespace MARTe;
 75    using namespace MARTe2Tutorial;
 76    SetErrorProcessFunction(&ErrorProcessExampleFunction);
 77    StreamString err;
 78
 79    bool ok = true;
 80    {
 81        StreamString configurationCfg = ""
 82                "+ConfigurationManager = {\n"
 83                "    Class = ObjectRegistryDatabaseMessageI\n"
 84                "}";
 85        //Force the string to be seeked to the beginning.
 86        configurationCfg.Seek(0LLU);
 87
 88        REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
 89        ConfigurationDatabase cdb;
 90
 91        StandardParser parser(configurationCfg, cdb, &err);
 92        parser.Parse();
 93        if (ok) {
 94            //After parsing the tree is pointing at the last leaf
 95            cdb.MoveToRoot();
 96            ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
 97        }
 98        else {
 99            StreamString errPrint;
100            errPrint.Printf("Failed to parse %s", err.Buffer());
101            REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
102        }
103    }
104    if (ok) {
105        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
106        DumpObjectRegistryDatabase(*ObjectRegistryDatabase::Instance(), 0u);
107    }
108    //Reload a new configuration
109    if (ok) {
110        StreamString app1Cfg = ""
111                "+App1 = {\n"
112                "    Class = ReferenceContainer\n"
113                "    +A = {\n"
114                "        Class = ReferenceContainer\n"
115                "        +B = {\n"
116                "            Class = ReferenceContainer\n"
117                "        }\n"
118                "    }\n"
119                "}";
120        ReferenceT<ConfigurationDatabase> cdbApp1(GlobalObjectsDatabase::Instance()->GetStandardHeap());
121        app1Cfg.Seek(0LLU);
122        StandardParser parserApp1(app1Cfg, *cdbApp1.operator ->(), &err);
123        ok = parserApp1.Parse();
124        if (ok) {
125            //After parsing the tree is pointing at the last leaf
126            ReferenceT<Message> msg(GlobalObjectsDatabase::Instance()->GetStandardHeap());
127            ConfigurationDatabase cdbMsg;
128            cdbMsg.Write("Function", "load");
129            cdbMsg.Write("Destination", "ConfigurationManager");
130            cdbApp1->MoveToRoot();
131            msg->Initialise(cdbMsg);
132            msg->Insert(cdbApp1);
133            ErrorManagement::ErrorType err = MessageI::SendMessage(msg);
134            ok = err.ErrorsCleared();
135            if (ok) {
136                REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the app1 configuration");
137                DumpObjectRegistryDatabase(*ObjectRegistryDatabase::Instance(), 0u);
138            }
139        }
140    }
141    //Change the configuration (purge first)
142    if (ok) {
143        ReferenceT<Message> msg(GlobalObjectsDatabase::Instance()->GetStandardHeap());
144        ConfigurationDatabase cdbMsg;
145        cdbMsg.Write("Function", "purge");
146        cdbMsg.Write("Destination", "ConfigurationManager");
147        ReferenceT<ConfigurationDatabase> cdbMsgPayload(GlobalObjectsDatabase::Instance()->GetStandardHeap());
148        cdbMsgPayload->Write("Root", "App1");
149        msg->Initialise(cdbMsg);
150        msg->Insert(cdbMsgPayload);
151        ErrorManagement::ErrorType err = MessageI::SendMessage(msg);
152        ok = err.ErrorsCleared();
153        if (ok) {
154            REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully purged the app1 configuration");
155            DumpObjectRegistryDatabase(*ObjectRegistryDatabase::Instance(), 0u);
156        }
157    }
158    if (ok) {
159        StreamString app2Cfg = ""
160                "+App1 = {\n"
161                "    Class = ReferenceContainer\n"
162                "    +A = {\n"
163                "        Class = ReferenceContainer\n"
164                "        +C = {\n"
165                "            Class = ReferenceContainer\n"
166                "            +B = {\n"
167                "                Class = ReferenceContainer\n"
168                "            }\n"
169                "        }\n"
170                "    }\n"
171                "}";
172
173        ReferenceT<ConfigurationDatabase> cdbApp2(GlobalObjectsDatabase::Instance()->GetStandardHeap());
174        app2Cfg.Seek(0LLU);
175        StandardParser parserApp2(app2Cfg, *cdbApp2.operator ->(), &err);
176        ok = parserApp2.Parse();
177        if (ok) {
178            //After parsing the tree is pointing at the last leaf
179            ReferenceT<Message> msg(GlobalObjectsDatabase::Instance()->GetStandardHeap());
180            ConfigurationDatabase cdbMsg;
181            cdbMsg.Write("Function", "load");
182            cdbMsg.Write("Destination", "ConfigurationManager");
183            msg->Initialise(cdbMsg);
184            msg->Insert(cdbApp2);
185            ErrorManagement::ErrorType err = MessageI::SendMessage(msg);
186            ok = err.ErrorsCleared();
187            if (ok) {
188                REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the app2 configuration");
189                DumpObjectRegistryDatabase(*ObjectRegistryDatabase::Instance(), 0u);
190            }
191        }
192    }
193    //Purge all the Objects!
194    MARTe::ObjectRegistryDatabase::Instance()->Purge();
195    return 0;
196}