Services
In order to promote uniformity in the management of threads, and in particular of the thread initialisation and destruction processes, the framework offers a thread service abstraction (see EmbeddedServiceI).
The following use-cases are covered: single-thread, multi-thread (each concurring for the same resource) and client oriented connection (e.g. web server).
The callback function (called by the service) shall have the following prototype: (MARTe::ErrorManagement::ErrorType (*)(MARTe::EmbeddedServiceI::ExecutionInfo &))
. The name of the callback function is registered by implementing the EmbeddedServiceMethodBinderT interface.
All service implementations will continuously call the callback function with a given state (represented by the input ExecutionInfo). The service will act accordingly to the returned value (see below).
Note
The callback function shall avoid blocking the execution and return as soon as possible.
Any of the EmbeddedServices offers a Start
and a Stop
method. The latter guarantees that the thread is killed if it not gracefully terminated by the application with-in a given timeout period.
All the thread parameters (affinity, stack, number of threads, …) can be changed using the specific service API or using the standard Initialise
method.
SingleThreadService
The SingleThreadService commands an EmbeddedThread which in turn continuously call the registered callback function with one of the stages set below.

Depending on the callback return value, the ExecutionInfo stage of each callback call is set as follows:
Stage |
Condition(s) |
StartupStage |
After |
If the callback returns an ErrorType which is not |
|
MainStage |
Until |
TerminationStage |
If the callback returns an ErrorType which is |
BadTerminationStage |
If the callback returns an ErrorType which is not |
AsyncTerminationStage |
If the thread was killed after trying to gracefully terminate with a |
The first time the SingleThreadService::Stop()
is called, the EmbeddedThread will wait for the callback function to return and will call it one last time with the ExecutionInfo stage set to BadTerminationStage
.
If, in the meanwhile, the SingleThreadService::Stop()
is called a second time, the thread will be killed (see Kill
in the Threads API) and the callback will be (asynchronously) called with the ExecutionInfo stage set to AsyncTerminationStage
.
Warning
The service can only be killed if a finite timeout was configured, otherwise it will wait forever to be gracefully stopped.
MultiThreadService
The MultiThreadService offers an equivalent function to the EmbeddedServiceI with one or more threads. The threads will concurrently call the callback function.

MultiClientService
The MultiClientService is a connection oriented implementation of the service described above. In particular the GetStageSpecific
of the ExecutionInfo is used to trigger connection oriented events:
StageSpecific |
Condition(s) |
WaitRequestStageSpecific |
Wait for a connection request. |
ServiceRequestStageSpecific |
Serve a specific request. |

The number of threads is allowed to be increased/decreased by the service between the values defined by GetMinimumNumberOfPoolThreads ()
and GetMaximumNumberOfPoolThreads ()
.
Note
The callback should not block and should return ErrorManagement::Timeout
while awaiting for a connection to be established.
After a connection is established (ServiceRequestStageSpecific) the callback shall return ErrorManagement::Completed
when the service has been completed.
Examples
SingleThreadService
The following is an example which highlights all the possible ExecutionInfo callback stages.
1/**
2 * @file SingleThreadServiceExample1.cpp
3 * @brief Source file for class SingleThreadServiceExample1
4 * @date 24/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 SingleThreadServiceExample1 (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23#define DLL_API
24/*---------------------------------------------------------------------------*/
25/* Standard header includes */
26/*---------------------------------------------------------------------------*/
27
28/*---------------------------------------------------------------------------*/
29/* Project header includes */
30/*---------------------------------------------------------------------------*/
31#include "AdvancedErrorManagement.h"
32#include "BasicTCPSocket.h"
33#include "ConfigurationDatabase.h"
34#include "ErrorLoggerExample.h"
35#include "EmbeddedServiceMethodBinderT.h"
36#include "ObjectRegistryDatabase.h"
37#include "StandardParser.h"
38#include "SingleThreadService.h"
39
40/*---------------------------------------------------------------------------*/
41/* Static definitions */
42/*---------------------------------------------------------------------------*/
43
44namespace MARTe2Tutorial {
45/**
46 * @brief a class that contains a single thread service with an embedded binder.
47 */
48class SingleThreadServiceExample1: public MARTe::Object, public MARTe::EmbeddedServiceMethodBinderT<SingleThreadServiceExample1> {
49
50public:
51 CLASS_REGISTER_DECLARATION()SingleThreadServiceExample1() :
52 MARTe::Object(), MARTe::EmbeddedServiceMethodBinderT<SingleThreadServiceExample1>(*this, &SingleThreadServiceExample1::ThreadCallback), service(
53 *this) {
54 counter = 0u;
55 }
56
57 virtual ~SingleThreadServiceExample1() {
58 using namespace MARTe;
59 if (GetName() != NULL) {
60 REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references "
61 "pointing at %s [%s]. The Object will "
62 "be safely deleted.",
63 GetName(), GetClassProperties()->GetName());
64 }
65 }
66
67 virtual bool Initialise(MARTe::StructuredDataI &data) {
68 bool ok = MARTe::Object::Initialise(data);
69 if (ok) {
70 ok = service.Initialise(data);
71 }
72 return ok;
73 }
74
75 MARTe::ErrorManagement::ErrorType ThreadCallback(MARTe::ExecutionInfo &info) {
76 using namespace MARTe;
77 ErrorManagement::ErrorType err;
78 if (info.GetStage() == ExecutionInfo::StartupStage) {
79 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::StartupStage");
80 }
81 else if (info.GetStage() == ExecutionInfo::MainStage) {
82 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::MainStage");
83 if (counter == 0u) {
84 err = ErrorManagement::Completed;
85 }
86 else {
87 err = ErrorManagement::FatalError;
88 }
89 }
90 else if (info.GetStage() == ExecutionInfo::TerminationStage) {
91 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::TerminationStage");
92 err = ErrorManagement::NoError;
93 counter++;
94 }
95 else if (info.GetStage() == ExecutionInfo::BadTerminationStage) {
96 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::BadTerminationStage");
97 counter++;
98 //Simulate error to force killing
99 while (true) {
100 Sleep::Sec(0.2);
101 }
102 }
103 else if (info.GetStage() == ExecutionInfo::AsyncTerminationStage) {
104 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::AsyncTerminationStage");
105 err = ErrorManagement::NoError;
106 }
107 Sleep::Sec(0.2);
108 return err;
109 }
110
111 MARTe::SingleThreadService service;
112 MARTe::uint32 counter;
113};
114
115CLASS_REGISTER(SingleThreadServiceExample1, "")
116}
117
118/*---------------------------------------------------------------------------*/
119/* Method definitions */
120/*---------------------------------------------------------------------------*/
121
122int main(int argc, char **argv) {
123 using namespace MARTe;
124 using namespace MARTe2Tutorial;
125 SetErrorProcessFunction(&ErrorProcessExampleFunction);
126
127 StreamString configurationCfg = ""
128 "+SingleThreadServiceExample1 = {\n"
129 " Class = SingleThreadServiceExample1\n"
130 " Timeout = 100\n" //100 ms
131 " CPUMask = 0x1\n"
132 "}";
133
134 REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
135 ConfigurationDatabase cdb;
136 StreamString err;
137 //Force the string to be seeked to the beginning.
138 configurationCfg.Seek(0LLU);
139 StandardParser parser(configurationCfg, cdb, &err);
140 bool ok = parser.Parse();
141 ObjectRegistryDatabase *ord = ObjectRegistryDatabase::Instance();
142 if (ok) {
143 //After parsing the tree is pointing at the last leaf
144 cdb.MoveToRoot();
145 ok = ord->Initialise(cdb);
146 }
147 else {
148 StreamString errPrint;
149 errPrint.Printf("Failed to parse %s", err.Buffer());
150 REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
151 }
152
153 ReferenceT<SingleThreadServiceExample1> singleThreadService;
154 if (ok) {
155 singleThreadService = ord->Find("SingleThreadServiceExample1");
156 ok = singleThreadService.IsValid();
157 }
158 if (ok) {
159 singleThreadService->service.Start();
160 while (singleThreadService->counter != 2) {
161 Sleep::Sec(0.2);
162 }
163 singleThreadService->service.Stop();
164 Sleep::Sec(0.2);
165 //Kill the service
166 singleThreadService->service.Stop();
167 }
168 //Purge all the Objects!
169 ObjectRegistryDatabase::Instance()->Purge();
170 return 0;
171}
MultiThreadService
This is an example similar to the above but with a MultiThreadService.
1/**
2 * @file MultiThreadServiceExample1.cpp
3 * @brief Source file for class MultiThreadServiceExample1
4 * @date 24/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 MultiThreadServiceExample1 (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23#define DLL_API
24/*---------------------------------------------------------------------------*/
25/* Standard header includes */
26/*---------------------------------------------------------------------------*/
27
28/*---------------------------------------------------------------------------*/
29/* Project header includes */
30/*---------------------------------------------------------------------------*/
31#include "AdvancedErrorManagement.h"
32#include "BasicTCPSocket.h"
33#include "ConfigurationDatabase.h"
34#include "ErrorLoggerExample.h"
35#include "EmbeddedServiceMethodBinderT.h"
36#include "ObjectRegistryDatabase.h"
37#include "StandardParser.h"
38#include "MultiThreadService.h"
39
40/*---------------------------------------------------------------------------*/
41/* Static definitions */
42/*---------------------------------------------------------------------------*/
43
44namespace MARTe2Tutorial {
45/**
46 * @brief a class that contains a single thread service with an embedded binder.
47 */
48class MultiThreadServiceExample1: public MARTe::Object, public MARTe::EmbeddedServiceMethodBinderT<MultiThreadServiceExample1> {
49
50public:
51 CLASS_REGISTER_DECLARATION()
52 MultiThreadServiceExample1() :
53 MARTe::Object(), MARTe::EmbeddedServiceMethodBinderT<MultiThreadServiceExample1>(*this, &MultiThreadServiceExample1::ThreadCallback), service(
54 *this) {
55 counter = NULL;
56 }
57
58 virtual ~MultiThreadServiceExample1() {
59 using namespace MARTe;
60 if (GetName() != NULL) {
61 REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references "
62 "pointing at %s [%s]. The Object will "
63 "be safely deleted.",
64 GetName(), GetClassProperties()->GetName());
65 }
66 delete counter;
67 }
68
69 virtual bool Initialise(MARTe::StructuredDataI &data) {
70 bool ok = MARTe::Object::Initialise(data);
71 if (ok) {
72 ok = service.Initialise(data);
73 }
74 if (ok) {
75 counter = new MARTe::uint32[service.GetNumberOfPoolThreads()];
76 MARTe::uint32 n;
77 for (n=0u; n<service.GetNumberOfPoolThreads(); n++) {
78 counter[n] = 0u;
79 }
80 }
81 return ok;
82 }
83
84 MARTe::ErrorManagement::ErrorType ThreadCallback(MARTe::ExecutionInfo &info) {
85 using namespace MARTe;
86 ErrorManagement::ErrorType err;
87 if (info.GetStage() == ExecutionInfo::StartupStage) {
88 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::StartupStage");
89 }
90 else if (info.GetStage() == ExecutionInfo::MainStage) {
91 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::MainStage");
92 if (counter[info.GetThreadNumber()] == 0u) {
93 err = ErrorManagement::Completed;
94 }
95 else {
96 err = ErrorManagement::FatalError;
97 }
98 }
99 else if (info.GetStage() == ExecutionInfo::TerminationStage) {
100 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::TerminationStage");
101 err = ErrorManagement::NoError;
102 counter[info.GetThreadNumber()]++;
103 }
104 else if (info.GetStage() == ExecutionInfo::BadTerminationStage) {
105 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::BadTerminationStage");
106 counter[info.GetThreadNumber()]++;
107 //Simulate error to force killing
108 while (true) {
109 Sleep::Sec(0.2);
110 }
111 }
112 else if (info.GetStage() == ExecutionInfo::AsyncTerminationStage) {
113 REPORT_ERROR(ErrorManagement::Information, "Callback called with ExecutionInfo::AsyncTerminationStage");
114 err = ErrorManagement::NoError;
115 }
116 Sleep::Sec(0.2);
117 return err;
118 }
119
120 MARTe::MultiThreadService service;
121 MARTe::uint32 *counter;
122};
123
124CLASS_REGISTER(MultiThreadServiceExample1, "")
125}
126
127/*---------------------------------------------------------------------------*/
128/* Method definitions */
129/*---------------------------------------------------------------------------*/
130
131int main(int argc, char **argv) {
132 using namespace MARTe;
133 using namespace MARTe2Tutorial;
134 SetErrorProcessFunction(&ErrorProcessExampleFunction);
135
136 StreamString configurationCfg = ""
137 "+MultiThreadServiceExample1 = {\n"
138 " Class = MultiThreadServiceExample1\n"
139 " NumberOfPoolThreads = 3\n"
140 " Timeout = 100\n" //100 ms
141 " CPUMask = 0x1\n"
142 "}";
143
144 REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
145 ConfigurationDatabase cdb;
146 StreamString err;
147 //Force the string to be seeked to the beginning.
148 configurationCfg.Seek(0LLU);
149 StandardParser parser(configurationCfg, cdb, &err);
150 bool ok = parser.Parse();
151 ObjectRegistryDatabase *ord = ObjectRegistryDatabase::Instance();
152 if (ok) {
153 //After parsing the tree is pointing at the last leaf
154 cdb.MoveToRoot();
155 ok = ord->Initialise(cdb);
156 }
157 else {
158 StreamString errPrint;
159 errPrint.Printf("Failed to parse %s", err.Buffer());
160 REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
161 }
162
163 ReferenceT<MultiThreadServiceExample1> multiThreadService;
164 if (ok) {
165 multiThreadService = ord->Find("MultiThreadServiceExample1");
166 ok = multiThreadService.IsValid();
167 }
168 if (ok) {
169 multiThreadService->service.Start();
170 uint32 n;
171 for (n=0u; n<multiThreadService->service.GetNumberOfPoolThreads(); n++) {
172 while (multiThreadService->counter[n] != 2) {
173 Sleep::Sec(0.2);
174 }
175 }
176 multiThreadService->service.Stop();
177 Sleep::Sec(0.2);
178 //Kill the service
179 multiThreadService->service.Stop();
180 }
181 //Purge all the Objects!
182 ObjectRegistryDatabase::Instance()->Purge();
183 return 0;
184}
MultiClientService
The custom component TCPSocketMessageProxyExample
forwards TCP messages into MARTe messages.
1/**
2 * @file TCPSocketMessageProxyExample.cpp
3 * @brief Source file for class TCPSocketMessageProxyExample
4 * @date 13/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 TCPSocketMessageProxyExample (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23#define DLL_API
24/*---------------------------------------------------------------------------*/
25/* Standard header includes */
26/*---------------------------------------------------------------------------*/
27
28/*---------------------------------------------------------------------------*/
29/* Project header includes */
30/*---------------------------------------------------------------------------*/
31#include "AdvancedErrorManagement.h"
32#include "ConfigurationDatabase.h"
33#include "Message.h"
34#include "MessageI.h"
35#include "StandardParser.h"
36#include "TCPSocketMessageProxyExample.h"
37
38/*---------------------------------------------------------------------------*/
39/* Static definitions */
40/*---------------------------------------------------------------------------*/
41
42/*---------------------------------------------------------------------------*/
43/* Method definitions */
44/*---------------------------------------------------------------------------*/
45
46namespace MARTe2Tutorial {
47
48TCPSocketMessageProxyExample::TCPSocketMessageProxyExample() :
49 MARTe::Object(), MARTe::EmbeddedServiceMethodBinderI(), tcpClientService(*this) {
50 waitForConnection = true;
51 mux.Create();
52 timeout = 10;
53
54}
55
56TCPSocketMessageProxyExample::~TCPSocketMessageProxyExample() {
57 using namespace MARTe;
58 if (tcpClientService.Stop() != ErrorManagement::NoError) {
59 if (tcpClientService.Stop() != ErrorManagement::NoError) {
60 REPORT_ERROR(ErrorManagement::Warning, "Could not Stop the tcpThreadService");
61 }
62 }
63 mux.UnLock();
64 mux.Close();
65 if (!socket.Close()) {
66 REPORT_ERROR(ErrorManagement::Warning, "Could not Close the socket");
67 }
68}
69
70bool TCPSocketMessageProxyExample::Initialise(MARTe::StructuredDataI & data) {
71 using namespace MARTe;
72 uint32 port;
73 bool ok = Object::Initialise(data);
74 if (ok) {
75 ok = data.Read("Port", port);
76 if (!ok) {
77 REPORT_ERROR(ErrorManagement::ParametersError, "Could not Read the Port parameter");
78 }
79 }
80 if (ok) {
81 ok = socket.Open();
82 if (!ok) {
83 REPORT_ERROR(ErrorManagement::ParametersError, "Could not Open server socket");
84 }
85 }
86 if (ok) {
87 ok = socket.Listen(port);
88 if (!ok) {
89 REPORT_ERROR(ErrorManagement::ParametersError, "Could not Listen on port %d", port);
90 }
91 }
92 if (ok) {
93 tcpClientService.SetName(GetName());
94 ok = (tcpClientService.Start() == ErrorManagement::NoError);
95 if (!ok) {
96 REPORT_ERROR(ErrorManagement::ParametersError, "Could not Start tcpClientService");
97 }
98 }
99 if (ok) {
100 REPORT_ERROR(ErrorManagement::Information, "Server listening in port %d", port);
101 }
102 return ok;
103}
104
105MARTe::ErrorManagement::ErrorType TCPSocketMessageProxyExample::Execute(MARTe::ExecutionInfo & info) {
106 using namespace MARTe;
107 ErrorManagement::ErrorType err;
108
109 if (info.GetStageSpecific() == MARTe::ExecutionInfo::WaitRequestStageSpecific) {
110 mux.Lock();
111 if (waitForConnection) {
112 waitForConnection = false;
113 mux.UnLock();
114 BasicTCPSocket *client = socket.WaitConnection(timeout);
115 if (client != NULL_PTR(BasicTCPSocket *)) {
116 REPORT_ERROR(ErrorManagement::Information, "Connection accepted!");
117 mux.Lock();
118 waitForConnection = true;
119 info.SetThreadSpecificContext(reinterpret_cast<void *>(client));
120 err = ErrorManagement::NoError;
121 mux.UnLock();
122 }
123 else {
124 mux.Lock();
125 waitForConnection = true;
126 err = ErrorManagement::Timeout;
127 mux.UnLock();
128 }
129 }
130 else {
131 mux.UnLock();
132 MARTe::Sleep::MSec(timeout);
133 err = ErrorManagement::Timeout;
134 }
135 }
136 if (info.GetStageSpecific() == MARTe::ExecutionInfo::ServiceRequestStageSpecific) {
137 BasicTCPSocket *client = reinterpret_cast<BasicTCPSocket *>(info.GetThreadSpecificContext());
138 if (client != NULL_PTR(BasicTCPSocket *)) {
139 const uint32 BUFFER_SIZE = 1024u;
140 char8 buffer[BUFFER_SIZE];
141 uint32 readBytes = BUFFER_SIZE;
142 MemoryOperationsHelper::Set(&buffer[0], '\0', BUFFER_SIZE);
143 if (client->Read(&buffer[0], readBytes)) {
144 StreamString configurationCfg = buffer;
145 REPORT_ERROR(ErrorManagement::ParametersError, "Received configuration message [size=%d]:%s", readBytes, configurationCfg.Buffer());
146 //Try to parse the configuration message
147 StreamString err;
148 //Force the string to be seeked to the beginning.
149 configurationCfg.Seek(0LLU);
150 ConfigurationDatabase msgCdb;
151 StandardParser parser(configurationCfg, msgCdb, &err);
152 ReferenceT<Message> msg(GlobalObjectsDatabase::Instance()->GetStandardHeap());
153 ErrorManagement::ErrorType msgError;
154 msgError.parametersError = !parser.Parse();
155 if (msgError.ErrorsCleared()) {
156 //After parsing the tree is pointing at the last leaf
157 msgCdb.MoveToRoot();
158 msgError.parametersError = !msg->Initialise(msgCdb);
159 if (!msgError.ErrorsCleared()) {
160 REPORT_ERROR(ErrorManagement::ParametersError, "Failed to initialise message");
161 }
162 }
163 else {
164 StreamString errPrint;
165 errPrint.Printf("Failed to parse %s", err.Buffer());
166 REPORT_ERROR(ErrorManagement::ParametersError, errPrint.Buffer());
167 }
168 if (msgError.ErrorsCleared()) {
169 msgError = MessageI::SendMessage(msg, this);
170 if (!msgError.ErrorsCleared()) {
171 REPORT_ERROR(ErrorManagement::ParametersError, "Error while sending message to destination %s with function %s",
172 msg->GetDestination().GetList(), msg->GetFunction().GetList());
173 }
174 }
175 readBytes = BUFFER_SIZE;
176 }
177 if (!client->Close()) {
178 REPORT_ERROR(ErrorManagement::ParametersError, "Failed to Close client connection");
179 }
180 delete client;
181 }
182 return MARTe::ErrorManagement::Completed;
183 }
184 return err;
185}
186
187CLASS_REGISTER(TCPSocketMessageProxyExample, "")
188}
Start the application with the -m parameter.
In order to change state, start the application and, in another console, type echo -e "Destination=StateMachine\nFunction=GOTOSTATE2" | nc 127.0.0.1 24680
.
1+TCPMessageProxy = {
2 Class = TCPSocketMessageProxyExample
3 Port = 24680
4}
5+StateMachine = {
6 Class = StateMachine
7 +INITIAL = {
8 Class = ReferenceContainer
9 +START = {
10 Class = StateMachineEvent
11 NextState = "STATE1"
12 NextStateError = "ERROR"
13 Timeout = 0
14 +ChangeToState1Msg = {
15 Class = Message
16 Destination = TestApp
17 Mode = ExpectsReply
18 Function = PrepareNextState
19 +Parameters = {
20 Class = ConfigurationDatabase
21 param1 = State1
22 }
23 }
24 +StartNextStateExecutionMsg = {
25 Class = Message
26 Destination = TestApp
27 Function = StartNextStateExecution
28 Mode = ExpectsReply
29 }
30 }
31 }
32 +STATE1 = {
33 Class = ReferenceContainer
34 +GOTOSTATE2 = {
35 Class = StateMachineEvent
36 NextState = "STATE2"
37 NextStateError = "ERROR"
38 Timeout = 0
39 +PrepareChangeToState2Msg = {
40 Class = Message
41 Destination = TestApp
42 Mode = ExpectsReply
43 Function = PrepareNextState
44 +Parameters = {
45 Class = ConfigurationDatabase
46 param1 = State2
47 }
48 }
49 +StopCurrentStateExecutionMsg = {
50 Class = Message
51 Destination = TestApp
52 Function = StopCurrentStateExecution
53 Mode = ExpectsReply
54 }
55 +StartNextStateExecutionMsg = {
56 Class = Message
57 Destination = TestApp
58 Function = StartNextStateExecution
59 Mode = ExpectsReply
60 }
61 }
62 +ERROR = {
63 Class = StateMachineEvent
64 NextState = "ERROR"
65 NextStateError = "ERROR"
66 }
67 }
68 +STATE2 = {
69 Class = ReferenceContainer
70 +GOTOSTATE1 = {
71 Class = StateMachineEvent
72 NextState = "STATE1"
73 NextStateError = "ERROR"
74 Timeout = 0
75 +PrepareChangeToState1Msg = {
76 Class = Message
77 Destination = TestApp
78 Mode = ExpectsReply
79 Function = PrepareNextState
80 +Parameters = {
81 Class = ConfigurationDatabase
82 param1 = State1
83 }
84 }
85 +StopCurrentStateExecutionMsg = {
86 Class = Message
87 Destination = TestApp
88 Function = StopCurrentStateExecution
89 Mode = ExpectsReply
90 }
91 +StartNextStateExecutionMsg = {
92 Class = Message
93 Destination = TestApp
94 Function = StartNextStateExecution
95 Mode = ExpectsReply
96 }
97 }
98 +ERROR = {
99 Class = StateMachineEvent
100 NextState = "ERROR"
101 NextStateError = "ERROR"
102 }
103 }
104 +ERROR = {
105 Class = ReferenceContainer
106 +ENTER = {
107 Class = ReferenceContainer
108 +StopCurrentStateExecutionMsg = {
109 Class = Message
110 Destination = TestApp
111 Function = StopCurrentStateExecution
112 Mode = ExpectsReply
113 }
114 +PrepareChangeToErrorMsg = {
115 Class = Message
116 Destination = TestApp
117 Mode = ExpectsReply
118 Function = PrepareNextState
119 +Parameters = {
120 Class = ConfigurationDatabase
121 param1 = StateError
122 }
123 }
124 +StartNextStateExecutionMsg = {
125 Class = Message
126 Destination = TestApp
127 Function = StartNextStateExecution
128 Mode = ExpectsReply
129 }
130 }
131 +RESET = {
132 Class = StateMachineEvent
133 NextState = "STATE1"
134 NextStateError = "STATE1"
135 Timeout = 0
136 +StopCurrentStateExecutionMsg = {
137 Class = Message
138 Destination = TestApp
139 Function = StopCurrentStateExecution
140 Mode = ExpectsReply
141 }
142 +PrepareChangeToState1Msg = {
143 Class = Message
144 Destination = TestApp
145 Mode = ExpectsReply
146 Function = PrepareNextState
147 +Parameters = {
148 Class = ConfigurationDatabase
149 param1 = State1
150 }
151 }
152 +StartNextStateExecutionMsg = {
153 Class = Message
154 Destination = TestApp
155 Function = StartNextStateExecution
156 Mode = ExpectsReply
157 }
158 }
159 }
160}
161$TestApp = {
162 Class = RealTimeApplication
163 +Functions = {
164 Class = ReferenceContainer
165 +GAMTimer = {
166 Class = IOGAM
167 InputSignals = {
168 Counter = {
169 DataSource = Timer
170 Type = uint32
171 }
172 Time = {
173 Frequency = 1
174 DataSource = Timer
175 Type = uint32
176 }
177 }
178 OutputSignals = {
179 Counter = {
180 DataSource = DDB1
181 Type = uint32
182 }
183 Time = {
184 DataSource = DDB1
185 Type = uint32
186 }
187 }
188 }
189 +GAMVariable1 = {
190 Class = VariableGAMExample1
191 Gains = {2, 3, 4}
192 InputSignals = {
193 Counter = {
194 DataSource = DDB1
195 Type = uint32
196 }
197 }
198 OutputSignals = {
199 GainCounter1Thread1 = {
200 DataSource = DDB1
201 Type = uint32
202 }
203 GainCounter2Thread1 = {
204 DataSource = DDB1
205 Type = uint32
206 }
207 GainCounter3Thread1 = {
208 DataSource = DDB1
209 Type = uint32
210 }
211 }
212 }
213 +GAMT1TSynchOut = {
214 Class = IOGAM
215 InputSignals = {
216 GainCounter1Thread1 = {
217 DataSource = DDB1
218 Type = uint32
219 }
220 GainCounter2Thread1 = {
221 DataSource = DDB1
222 Type = uint32
223 }
224 GainCounter3Thread1 = {
225 DataSource = DDB1
226 Type = uint32
227 }
228 }
229 OutputSignals = {
230 GainCounter1Thread1 = {
231 DataSource = RTThreadSynch
232 Type = uint32
233 }
234 GainCounter2Thread1 = {
235 DataSource = RTThreadSynch
236 Type = uint32
237 }
238 GainCounter3Thread1 = {
239 DataSource = RTThreadSynch
240 Type = uint32
241 }
242 }
243 }
244 +GAMT1T2Interface = {
245 Class = IOGAM
246 InputSignals = {
247 GainCounter1Thread1 = {
248 DataSource = RTThreadSynch
249 Type = uint32
250 Samples = 2 //Run at half the frequency of thread 1
251 }
252 GainCounter2Thread1 = {
253 DataSource = RTThreadSynch
254 Type = uint32
255 Samples = 2 //Run at half the frequency of thread 1
256 }
257 GainCounter3Thread1 = {
258 DataSource = RTThreadSynch
259 Type = uint32
260 Samples = 2 //Run at half the frequency of thread 1
261 }
262 }
263 OutputSignals = {
264 GainCounter1Thread2 = {
265 DataSource = DDB1
266 Type = uint32
267 Samples = 1
268 NumberOfDimensions = 1
269 NumberOfElements = 2 //2 elements for each cycle (as it waits for 2 samples)
270 }
271 GainCounter2Thread2 = {
272 DataSource = DDB1
273 Type = uint32
274 Samples = 1
275 NumberOfDimensions = 1
276 NumberOfElements = 2 //2 elements for each cycle (as it waits for 2 samples)
277 }
278 GainCounter3Thread2 = {
279 DataSource = DDB1
280 Type = uint32
281 Samples = 1
282 NumberOfDimensions = 1
283 NumberOfElements = 2 //2 elements for each cycle (as it waits for 2 samples)
284 }
285 }
286 }
287 +GAMT1T3Interface = {
288 Class = IOGAM
289 InputSignals = {
290 GainCounter1Thread1 = {
291 DataSource = RTThreadSynch
292 Type = uint32
293 Samples = 4 //Run at one quarter of the frequency of thread 1
294 }
295 GainCounter2Thread1 = {
296 DataSource = RTThreadSynch
297 Type = uint32
298 Samples = 4 //Run at one quarter the frequency of thread 1
299 }
300 GainCounter3Thread1 = {
301 DataSource = RTThreadSynch
302 Type = uint32
303 Samples = 4 //Run at one quarter the frequency of thread 1
304 }
305 }
306 OutputSignals = {
307 GainCounter1Thread3 = {
308 DataSource = DDB1
309 Type = uint32
310 Samples = 1
311 NumberOfDimensions = 1
312 NumberOfElements = 4 //4 elements for each cycle (as it waits for 4 samples)
313 }
314 GainCounter2Thread3 = {
315 DataSource = DDB1
316 Type = uint32
317 Samples = 1
318 NumberOfDimensions = 1
319 NumberOfElements = 4 //4 elements for each cycle (as it waits for 4 samples)
320 }
321 GainCounter3Thread3 = {
322 DataSource = DDB1
323 Type = uint32
324 Samples = 1
325 NumberOfDimensions = 1
326 NumberOfElements = 4 //4 elements for each cycle (as it waits for 4 samples)
327 }
328 }
329 }
330 +GAMDisplayThread1 = {
331 Class = IOGAM
332 InputSignals = {
333 Counter = {
334 DataSource = DDB1
335 Type = uint32
336 }
337 GainCounter1Thread1 = {
338 DataSource = DDB1
339 Type = uint32
340 }
341 GainCounter2Thread1 = {
342 DataSource = DDB1
343 Type = uint32
344 }
345 GainCounter3Thread1 = {
346 DataSource = DDB1
347 Type = uint32
348 }
349 }
350 OutputSignals = {
351 Counter = {
352 DataSource = LoggerDataSource
353 Type = uint32
354 }
355 GainCounter1Thread1 = {
356 DataSource = LoggerDataSource
357 Type = uint32
358 }
359 GainCounter2Thread1 = {
360 DataSource = LoggerDataSource
361 Type = uint32
362 }
363 GainCounter3Thread1 = {
364 DataSource = LoggerDataSource
365 Type = uint32
366 }
367 }
368 }
369 +GAMDisplayThread2 = {
370 Class = IOGAM
371 InputSignals = {
372 GainCounter1Thread2 = {
373 DataSource = DDB1
374 Type = uint32
375 }
376 GainCounter2Thread2 = {
377 DataSource = DDB1
378 Type = uint32
379 }
380 GainCounter3Thread2 = {
381 DataSource = DDB1
382 Type = uint32
383 }
384 }
385 OutputSignals = {
386 GainCounter1Thread2 = {
387 DataSource = LoggerDataSource
388 Type = uint32
389 NumberOfDimensions = 1
390 NumberOfElements = 2
391 }
392 GainCounter2Thread2 = {
393 DataSource = LoggerDataSource
394 Type = uint32
395 NumberOfDimensions = 1
396 NumberOfElements = 2
397 }
398 GainCounter3Thread2 = {
399 DataSource = LoggerDataSource
400 Type = uint32
401 NumberOfDimensions = 1
402 NumberOfElements = 2
403 }
404 }
405 }
406 +GAMDisplayThread3 = {
407 Class = IOGAM
408 InputSignals = {
409 GainCounter1Thread3 = {
410 DataSource = DDB1
411 Type = uint32
412 }
413 GainCounter2Thread3 = {
414 DataSource = DDB1
415 Type = uint32
416 }
417 GainCounter3Thread3 = {
418 DataSource = DDB1
419 Type = uint32
420 }
421 }
422 OutputSignals = {
423 GainCounter1Thread3 = {
424 DataSource = LoggerDataSource
425 Type = uint32
426 NumberOfDimensions = 1
427 NumberOfElements = 4
428 }
429 GainCounter2Thread3 = {
430 DataSource = LoggerDataSource
431 Type = uint32
432 NumberOfDimensions = 1
433 NumberOfElements = 4
434 }
435 GainCounter3Thread3 = {
436 DataSource = LoggerDataSource
437 Type = uint32
438 NumberOfDimensions = 1
439 NumberOfElements = 4
440 }
441 }
442 }
443 }
444 +Data = {
445 Class = ReferenceContainer
446 DefaultDataSource = DDB1
447 +DDB1 = {
448 Class = GAMDataSource
449 }
450 +LoggerDataSource = {
451 Class = LoggerDataSource
452 }
453 +Timings = {
454 Class = TimingDataSource
455 }
456 +RTThreadSynch = {
457 Class = RealTimeThreadSynchronisation
458 Timeout = 5000 //Timeout in ms to wait for the thread to cycle.
459 }
460 +Timer = {
461 Class = LinuxTimer
462 SleepNature = "Default"
463 Signals = {
464 Counter = {
465 Type = uint32
466 }
467 Time = {
468 Type = uint32
469 }
470 }
471 }
472 }
473 +States = {
474 Class = ReferenceContainer
475 +State1 = {
476 Class = RealTimeState
477 +Threads = {
478 Class = ReferenceContainer
479 +Thread1 = {
480 Class = RealTimeThread
481 CPUs = 0x1
482 Functions = {GAMTimer GAMVariable1 GAMT1TSynchOut GAMDisplayThread1}
483 }
484 }
485 }
486 +State2 = {
487 Class = RealTimeState
488 +Threads = {
489 Class = ReferenceContainer
490 +Thread1 = {
491 Class = RealTimeThread
492 CPUs = 0x1
493 Functions = {GAMTimer GAMVariable1 GAMT1TSynchOut GAMDisplayThread1}
494 }
495 +Thread2 = {
496 Class = RealTimeThread
497 CPUs = 0x2
498 Functions = {GAMT1T2Interface GAMDisplayThread2}
499 }
500 +Thread3 = {
501 Class = RealTimeThread
502 CPUs = 0x4
503 Functions = {GAMT1T3Interface GAMDisplayThread3}
504 }
505 }
506 }
507 +StateError = {
508 Class = RealTimeState
509 +Threads = {
510 Class = ReferenceContainer
511 +Thread1 = {
512 Class = RealTimeThread
513 CPUs = 0x1
514 Functions = {GAMTimer}
515 }
516 }
517 }
518 }
519 +Scheduler = {
520 Class = GAMScheduler
521 TimingDataSource = Timings
522 }
523}
Instructions on how to compile and execute the examples can be found here.