Skip to content

Commit b3ce514

Browse files
Generate code for interface servers (#465)
* Refs #23069. Skeleton for server creation code. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Skeleton for server class. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Initial implementation for run and stop. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Request validation. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Initial processing code. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Prepare method per operation. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Thread pool implementation. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate operation prototypes. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate operation empty implementations. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate skeleton for calling operations. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Code for calling basic operations. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Code for handling user exceptions. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Code for output feed writers. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Code for handling output feed operations. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Refactor to improve readability. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate code to handle output feed cancellation. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Fix client code for output feed cancellation. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Infrastructure for input feed processing. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate code for input feed readers. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Improve readability. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Code for operations with input feeds. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate declatation of implementation interface. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. ServerLogic depends on implementation interface. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Generate empty implementation interface. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Fix linters. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Avoid processing `feed_cancel_` when not generated. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Log error when trying to cancel a non-feed request. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23069. Cancel requests before terminating thread pool. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23079. Change dll export macro. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23079. Remove unnecessary namespace aliasing. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23079. Remove detail namespace in server implementation. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #23079. Avoid nested structures (not supported by Swig). Signed-off-by: Miguel Company <miguelcompany@eprosima.com> --------- Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
1 parent c9ff1be commit b3ce514

File tree

9 files changed

+1084
-17
lines changed

9 files changed

+1084
-17
lines changed

src/main/java/com/eprosima/fastcdr/idl/templates/FastCdrCommon.stg

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ paramTypeByRef(typecode) ::= <%
2626
$typecode.cppTypename$&
2727
%>
2828

29-
paramTypeByValue(typecode, feed) ::= <%
29+
paramTypeByValue(typecode, feed, is_server) ::= <%
3030
$if(feed)$
31+
$if(is_server)$
32+
eprosima::fastdds::dds::rpc::RpcServerReader<$typecode.cppTypename$>&
33+
$else$
3134
std::shared_ptr<eprosima::fastdds::dds::rpc::RpcClientWriter<$typecode.cppTypename$>>&
35+
$endif$
3236
$else$
3337
$if(typecode.primitive)$
3438
$typecode.cppTypename$
@@ -39,7 +43,7 @@ $endif$
3943
%>
4044

4145
paramDeclarations(params, initialSeparator="") ::= <<
42-
$if(params)$$initialSeparator$$endif$$params : {param | /*$param.comment$*/ $if(param.output)$$paramTypeByRef(typecode=param.typecode)$$else$$paramTypeByValue(typecode=param.typecode, feed=param.annotationFeed)$$endif$ $param.name$}; anchor, separator=",\n"$
46+
$if(params)$$initialSeparator$$endif$$params : {param | /*$param.comment$*/ $if(param.output)$$paramTypeByRef(typecode=param.typecode)$$else$$paramTypeByValue(typecode=param.typecode, feed=param.annotationFeed, is_server=false)$$endif$ $param.name$}; anchor, separator=",\n"$
4347
>>
4448

4549
object_serialization(ctx, object) ::= <<

src/main/java/com/eprosima/fastcdr/idl/templates/TypesHeader.stg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ exception(ctx, parent, exception, extensions) ::= <<
129129
* @brief This class implements the user exception $exception.scopedname$
130130
* @ingroup $ctx.trimfilename$
131131
*/
132-
class $ctx.fileNameUpper$_DllAPI $exception.name$ : public eprosima::fastdds::dds::rpc::RpcOperationError
132+
class eProsima_user_DllExport $exception.name$ : public eprosima::fastdds::dds::rpc::RpcOperationError
133133
{
134134
public:
135135

@@ -193,7 +193,7 @@ interface(ctx, parent, interface, export_list) ::= <<
193193
* @brief This class represents the interface $interface.name$ defined by the user in the IDL file.
194194
* @ingroup $ctx.trimfilename$
195195
*/
196-
class $ctx.fileNameUpper$_DllAPI $interface.name$ $if(interface.bases)$: $interface.bases : {base |public $base.scopedname$}; separator=", "$$endif$
196+
class eProsima_user_DllExport $interface.name$ $if(interface.bases)$: $interface.bases : {base |public $base.scopedname$}; separator=", "$$endif$
197197
{
198198
public:
199199
virtual ~$interface.name$() = default;

src/main/java/com/eprosima/fastdds/fastddsgen.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,9 @@ private Project parseIDL(
809809
tmanager.addGroup("com/eprosima/fastdds/idl/templates/DDSPubSubTypeSource.stg");
810810
tmanager.addGroup("com/eprosima/fastdds/idl/templates/ClientHeader.stg");
811811
tmanager.addGroup("com/eprosima/fastdds/idl/templates/ClientSource.stg");
812+
tmanager.addGroup("com/eprosima/fastdds/idl/templates/ServerHeader.stg");
813+
tmanager.addGroup("com/eprosima/fastdds/idl/templates/ServerSource.stg");
814+
tmanager.addGroup("com/eprosima/fastdds/idl/templates/ServerImplementation.stg");
812815

813816
if (generate_typeobjectsupport_)
814817
{
@@ -1072,6 +1075,21 @@ private Project parseIDL(
10721075
{
10731076
project.addCommonSrcFile(relative_dir + ctx.getFilename() + "Client.cxx");
10741077
}
1078+
if (returnedValue &=
1079+
Utils.writeFile(output_dir + ctx.getFilename() + "Server.hpp",
1080+
maintemplates.getTemplate("com/eprosima/fastdds/idl/templates/ServerHeader.stg"), m_replace))
1081+
{
1082+
project.addCommonIncludeFile(relative_dir + ctx.getFilename() + "Server.hpp");
1083+
}
1084+
if (returnedValue &=
1085+
Utils.writeFile(output_dir + ctx.getFilename() + "Server.cxx",
1086+
maintemplates.getTemplate("com/eprosima/fastdds/idl/templates/ServerSource.stg"), m_replace))
1087+
{
1088+
project.addCommonSrcFile(relative_dir + ctx.getFilename() + "Server.cxx");
1089+
}
1090+
returnedValue &=
1091+
Utils.writeFile(output_dir + ctx.getFilename() + "ServerImpl.hpp",
1092+
maintemplates.getTemplate("com/eprosima/fastdds/idl/templates/ServerImplementation.stg"), m_replace);
10751093
}
10761094

10771095
if (ctx.existsLastStructure())

src/main/java/com/eprosima/fastdds/idl/grammar/Operation.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ public boolean isAnnotationMutable()
6565
return false;
6666
}
6767

68+
public boolean isHasInputFeeds()
69+
{
70+
return m_hasInputFeeds;
71+
}
72+
6873
@Override
6974
public void add(com.eprosima.idl.parser.tree.Param param)
7075
{
@@ -81,6 +86,7 @@ public void add(com.eprosima.idl.parser.tree.Param param)
8186
{
8287
// Take note that there is at least one input feed
8388
m_context.setThereIsInputFeed(true);
89+
m_hasInputFeeds = true;
8490
}
8591
}
8692

@@ -242,4 +248,5 @@ public StructTypeCode getResultTypeCode()
242248
private StructTypeCode m_in_type = null;
243249
private StructTypeCode m_out_type = null;
244250
private StructTypeCode m_result_type = null;
251+
private boolean m_hasInputFeeds = false;
245252
}

src/main/java/com/eprosima/fastdds/idl/templates/ClientHeader.stg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ $definition_list$
4545
>>
4646

4747
interface(ctx, parent, interface, export_list) ::= <<
48-
extern $ctx.fileNameUpper$_DllAPI std::shared_ptr<$interface.name$> create_$interface.name$Client(
48+
extern eProsima_user_DllExport std::shared_ptr<$interface.name$> create_$interface.name$Client(
4949
eprosima::fastdds::dds::DomainParticipant& part,
5050
const char* service_name,
5151
const eprosima::fastdds::dds::RequesterQos& qos);

src/main/java/com/eprosima/fastdds/idl/templates/ClientSource.stg

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,7 @@ $if(operation.annotationFeed)$
408408
bool& should_remove) override
409409
{
410410
should_remove = false;
411-
if (cancelled_ ||
412-
(req_info.related_sample_identity != info.related_sample_identity))
411+
if (req_info.related_sample_identity != info.related_sample_identity)
413412
{
414413
return;
415414
}
@@ -433,23 +432,26 @@ $if(operation.annotationFeed)$
433432
{
434433
const auto& out = result.result.value();
435434
{
436-
if (out.return_.has_value())
435+
if (out.finished_.has_value())
437436
{
438-
// Store the return value
437+
// Store the finished value
439438
std::lock_guard<std::mutex> _(mtx_);
440-
queue_.push(out.return_.value());
439+
finished_ = true;
441440
cv_.notify_all();
441+
}
442+
else if (out.return_.has_value())
443+
{
444+
if (!cancelled_)
445+
{
446+
// Store the return value
447+
std::lock_guard<std::mutex> _(mtx_);
448+
queue_.push(out.return_.value());
449+
cv_.notify_all();
450+
}
442451

443452
// Should be kept in order to receive further values
444453
should_remove = false;
445454
}
446-
else if (out.finished_.has_value())
447-
{
448-
// Store the finished value
449-
std::lock_guard<std::mutex> _(mtx_);
450-
finished_ = true;
451-
cv_.notify_all();
452-
}
453455
else
454456
{
455457
set_invalid_reply(*this);
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
group ProtocolHeader;
16+
17+
import "eprosima.stg"
18+
import "com/eprosima/fastcdr/idl/templates/FastCdrCommon.stg"
19+
20+
main(ctx, definitions) ::= <<
21+
$fileHeader(ctx=ctx, file=[ctx.filename, "Server.hpp"], description=["Server implementation for interfaces"])$
22+
23+
#ifndef FAST_DDS_GENERATED__$ctx.headerGuardName$_SERVER_HPP
24+
#define FAST_DDS_GENERATED__$ctx.headerGuardName$_SERVER_HPP
25+
26+
#include <memory>
27+
28+
#include <fastdds/dds/domain/DomainParticipant.hpp>
29+
#include <fastdds/dds/domain/qos/ReplierQos.hpp>
30+
#include <fastdds/dds/rpc/exceptions.hpp>
31+
#include <fastdds/dds/rpc/interfaces.hpp>
32+
#include <fastdds/rtps/common/Guid.hpp>
33+
#include <fastdds/rtps/common/RemoteLocators.hpp>
34+
35+
#include "$ctx.filename$.hpp"
36+
37+
$definitions; separator="\n"$
38+
39+
#endif // FAST_DDS_GENERATED__$ctx.headerGuardName$_CLIENT_HPP
40+
41+
>>
42+
43+
module(ctx, parent, module, definition_list) ::= <<
44+
namespace $module.name$ {
45+
46+
$definition_list$
47+
48+
} // namespace $module.name$
49+
50+
>>
51+
52+
interface(ctx, parent, interface, export_list) ::= <<
53+
/**
54+
* @brief Context for a client request.
55+
*/
56+
struct $interface.name$Server_ClientContext
57+
{
58+
virtual ~$interface.name$Server_ClientContext() = default;
59+
60+
/**
61+
* @brief Get the GUID of the client that made the request.
62+
*
63+
* @return The GUID of the client that made the request.
64+
*/
65+
virtual const eprosima::fastdds::rtps::GUID_t& get_client_id() const = 0;
66+
67+
/**
68+
* @brief Get the locators of the client that made the request.
69+
*
70+
* @return The locators of the client that made the request.
71+
*/
72+
virtual const eprosima::fastdds::rtps::RemoteLocatorList& get_client_locators() const = 0;
73+
};
74+
75+
struct $interface.name$Server_IServerImplementation
76+
{
77+
virtual ~$interface.name$Server_IServerImplementation() = default;
78+
79+
$interface.all_operations:{op | $operation_prototype(op)$}; separator="\n\n"$
80+
};
81+
82+
struct $interface.name$Server
83+
{
84+
virtual ~$interface.name$Server() = default;
85+
86+
/**
87+
* @brief Run the server.
88+
*
89+
* This method starts the server and begins processing requests.
90+
* The method will block until the server is stopped.
91+
*/
92+
virtual void run() = 0;
93+
94+
/**
95+
* @brief Stop the server.
96+
*
97+
* This method stops the server and releases all resources.
98+
* It will cancel all pending requests, and wait for all processing threads to finish before returning.
99+
*/
100+
virtual void stop() = 0;
101+
102+
};
103+
104+
/**
105+
* @brief Create a $interface.name$Server instance.
106+
*
107+
* @param part The DomainParticipant to use for the server.
108+
* @param service_name The name of the service.
109+
* @param qos The QoS settings for the server.
110+
* @param thread_pool_size The size of the thread pool to use for processing requests.
111+
* When set to 0, a new thread will be created when no threads are available.
112+
* @param implementation The implementation of the server interface.
113+
*/
114+
extern eProsima_user_DllExport std::shared_ptr<$interface.name$Server> create_$interface.name$Server(
115+
eprosima::fastdds::dds::DomainParticipant& part,
116+
const char* service_name,
117+
const eprosima::fastdds::dds::ReplierQos& qos,
118+
size_t thread_pool_size,
119+
std::shared_ptr<$interface.name$Server_IServerImplementation> implementation);
120+
>>
121+
122+
operation_prototype(op) ::= <<
123+
$if(op.annotationFeed)$
124+
virtual void $op.name$(
125+
const $interface.name$Server_ClientContext& info,
126+
$if(op.parameters)$
127+
$operation_parameters(op.parameters)$,
128+
$endif$
129+
/*result*/ eprosima::fastdds::dds::rpc::RpcServerWriter<$paramRetType(op.rettype)$>& result_writer) = 0;
130+
$else$
131+
$if(op.parameters)$
132+
virtual $paramRetType(op.rettype)$ $op.name$(
133+
const $interface.name$Server_ClientContext& info,
134+
$operation_parameters(op.parameters)$) = 0;
135+
$else$
136+
virtual $paramRetType(op.rettype)$ $op.name$(
137+
const $interface.name$Server_ClientContext& info) = 0;
138+
$endif$
139+
$endif$
140+
>>
141+
142+
operation_parameters(params) ::= <<
143+
$params : {param | /*$param.comment$*/ $if(param.output)$$paramTypeByRef(typecode=param.typecode)$$else$$paramTypeByValue(typecode=param.typecode, feed=param.annotationFeed, is_server=true)$$endif$ $param.name$}; anchor, separator=",\n"$
144+
>>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
group ProtocolHeader;
16+
17+
import "eprosima.stg"
18+
import "com/eprosima/fastcdr/idl/templates/FastCdrCommon.stg"
19+
20+
main(ctx, definitions) ::= <<
21+
$fileHeader(ctx=ctx, file=[ctx.filename, "ServerImpl.hpp"], description=["Server implementation for interfaces"])$
22+
23+
#ifndef FAST_DDS_GENERATED__$ctx.headerGuardName$_SERVERIMPL_HPP
24+
#define FAST_DDS_GENERATED__$ctx.headerGuardName$_SERVERIMPL_HPP
25+
26+
#include "$ctx.filename$.hpp"
27+
#include "$ctx.filename$Server.hpp"
28+
29+
$definitions; separator="\n"$
30+
31+
#endif // FAST_DDS_GENERATED__$ctx.headerGuardName$_SERVERIMPL_HPP
32+
33+
>>
34+
35+
module(ctx, parent, module, definition_list) ::= <<
36+
namespace $module.name$ {
37+
38+
$definition_list$
39+
40+
} // namespace $module.name$
41+
42+
>>
43+
44+
interface(ctx, parent, interface, export_list) ::= <<
45+
//{ interface $interface.name$
46+
47+
struct $interface.name$ServerImplementation :
48+
public $interface.name$Server_IServerImplementation
49+
{
50+
51+
$interface.all_operations:{op | $operation_implementation(interface, op)$}; separator="\n"$
52+
53+
};
54+
55+
//} interface $interface.name$
56+
57+
>>
58+
59+
operation_implementation(interface, op) ::= <<
60+
$if(op.annotationFeed)$
61+
void $op.name$(
62+
const $interface.name$Server_ClientContext& info,
63+
$if(op.parameters)$
64+
$operation_parameters(op.parameters)$,
65+
$endif$
66+
/*result*/ eprosima::fastdds::dds::rpc::RpcServerWriter<$paramRetType(op.rettype)$>& result_writer) override
67+
$else$
68+
$if(op.parameters)$
69+
$paramRetType(op.rettype)$ $op.name$(
70+
const $interface.name$Server_ClientContext& info,
71+
$operation_parameters(op.parameters)$) override
72+
$else$
73+
$paramRetType(op.rettype)$ $op.name$(
74+
const $interface.name$Server_ClientContext& info) override
75+
$endif$
76+
$endif$
77+
{
78+
static_cast<void>(info);
79+
$op.parameters : {param | static_cast<void>($param.name$);}; anchor, separator="\n"$
80+
$if(op.annotationFeed)$
81+
static_cast<void>(result_writer);
82+
$endif$
83+
throw eprosima::fastdds::dds::rpc::RemoteUnsupportedError("Operation '$op.name$' is not implemented");
84+
}
85+
>>
86+
87+
operation_parameters(params) ::= <<
88+
$params : {param | /*$param.comment$*/ $if(param.output)$$paramTypeByRef(typecode=param.typecode)$$else$$paramTypeByValue(typecode=param.typecode, feed=param.annotationFeed, is_server=true)$$endif$ $param.name$}; anchor, separator=",\n"$
89+
>>

0 commit comments

Comments
 (0)