Skip to content

Commit 919f881

Browse files
committed
Implement allocator refactor for type support structs
Signed-off-by: methylDragon <[email protected]>
1 parent 8f55ada commit 919f881

File tree

2 files changed

+247
-52
lines changed

2 files changed

+247
-52
lines changed

include/rosidl_dynamic_typesupport/dynamic_message_type_support_struct.h

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern "C"
2020
{
2121
#endif
2222

23+
#include <rcutils/allocator.h>
2324
#include <rcutils/types/rcutils_ret.h>
2425
#include <rosidl_runtime_c/message_type_support_struct.h>
2526
#include <rosidl_runtime_c/type_description/type_description__struct.h>
@@ -48,6 +49,8 @@ extern "C"
4849
// outlives those downstream classes.
4950
typedef struct rosidl_dynamic_message_type_support_impl_s
5051
{
52+
rcutils_allocator_t allocator;
53+
5154
rosidl_type_hash_t * type_hash;
5255
rosidl_runtime_c__type_description__TypeDescription * type_description;
5356

@@ -68,21 +71,70 @@ typedef struct rosidl_dynamic_message_type_support_impl_s
6871
rosidl_dynamic_typesupport_dynamic_data_t * dynamic_message;
6972
} rosidl_dynamic_message_type_support_impl_t;
7073

74+
/// Return a zero initialized rosidl_dynamic_message_type_support_impl_t
75+
/**
76+
* \return A zero initialized dynamic message typesupport handle impl.
77+
*/
78+
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
79+
rosidl_dynamic_message_type_support_impl_t
80+
rosidl_get_zero_initialized_dynamic_message_type_support_impl(void);
81+
7182
/// Init a dynamic message type support handle
7283
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
7384
rcutils_ret_t
85+
rosidl_dynamic_message_type_support_handle_init(
86+
rosidl_dynamic_typesupport_serialization_support_t * serialization_support,
87+
const rosidl_type_hash_t * type_hash,
88+
const rosidl_runtime_c__type_description__TypeDescription * type_description,
89+
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources,
90+
rcutils_allocator_t * allocator,
91+
rosidl_message_type_support_t * ts);
92+
93+
/// Finalize a dynamic message type support handle
94+
/**
95+
* This should only be used to finalize a dynamic message type support handle obtained with
96+
* `rosidl_dynamic_message_type_support_handle_create()`, which has dynamically allocated members.
97+
* Using this on a statically allocated typesupport will cause undefined behavior!
98+
* (Static memory will get freed in that case.)
99+
*/
100+
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
101+
rcutils_ret_t
102+
rosidl_dynamic_message_type_support_handle_fini(rosidl_message_type_support_t * ts);
103+
104+
/// Init a dynamic message type support handle impl
105+
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
106+
rcutils_ret_t
107+
rosidl_dynamic_message_type_support_impl_init(
108+
rosidl_dynamic_typesupport_serialization_support_t * serialization_support,
109+
const rosidl_type_hash_t * type_hash,
110+
const rosidl_runtime_c__type_description__TypeDescription * type_description,
111+
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources,
112+
rcutils_allocator_t * allocator,
113+
rosidl_dynamic_message_type_support_impl_t * ts);
114+
115+
/// Finalize a dynamic message type support handle impl
116+
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
117+
rcutils_ret_t
118+
rosidl_dynamic_message_type_support_impl_fini(rosidl_dynamic_message_type_support_impl_t * ts);
119+
120+
/// Create, then init a dynamic message type support handle
121+
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
122+
rcutils_ret_t
74123
rosidl_dynamic_message_type_support_handle_create(
75124
rosidl_dynamic_typesupport_serialization_support_t * serialization_support,
76125
const rosidl_type_hash_t * type_hash,
77126
const rosidl_runtime_c__type_description__TypeDescription * type_description,
78127
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources,
128+
rcutils_allocator_t * allocator,
79129
rosidl_message_type_support_t ** ts);
80130

81-
/// Destroy a rosidl_message_type_support_t obtained with
82-
/// `rmw_dynamic_message_type_support_handle_create()`, which has dynamically allocated members
83-
///
84-
/// NOTE: Using this on a statically allocated typesupport will cause undefined behavior!
85-
/// (Static memory will get freed in that case.)
131+
/// Finilaize, then destroy a dynamic message type support handle
132+
/**
133+
* This should only be used to destroy a dynamic message type support handle obtained with
134+
* `rosidl_dynamic_message_type_support_handle_create()`, which has dynamically allocated members.
135+
* Using this on a statically allocated typesupport will cause undefined behavior!
136+
* (Static memory will get freed in that case.)
137+
*/
86138
ROSIDL_DYNAMIC_TYPESUPPORT_PUBLIC
87139
rcutils_ret_t
88140
rosidl_dynamic_message_type_support_handle_destroy(rosidl_message_type_support_t * ts);

src/dynamic_message_type_support_struct.c

Lines changed: 190 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,47 +25,135 @@
2525
#include "rosidl_dynamic_typesupport/identifier.h"
2626

2727

28+
rosidl_dynamic_message_type_support_impl_t
29+
rosidl_get_zero_initialized_dynamic_message_type_support_impl(void)
30+
{
31+
static rosidl_dynamic_message_type_support_impl_t zero_typesupport_handle_impl = {
32+
// .allocator = {0, 0, 0, 0, 0},
33+
.type_hash = NULL,
34+
.type_description = NULL,
35+
.type_description_sources = NULL,
36+
.serialization_support = NULL,
37+
.dynamic_message_type = NULL,
38+
.dynamic_message = NULL
39+
};
40+
zero_typesupport_handle_impl.allocator = rcutils_get_default_allocator();
41+
return zero_typesupport_handle_impl;
42+
}
43+
2844
rcutils_ret_t
29-
rosidl_dynamic_message_type_support_handle_create(
45+
rosidl_dynamic_message_type_support_handle_init(
3046
rosidl_dynamic_typesupport_serialization_support_t * serialization_support,
3147
const rosidl_type_hash_t * type_hash,
3248
const rosidl_runtime_c__type_description__TypeDescription * type_description,
3349
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources,
34-
rosidl_message_type_support_t ** ts)
50+
rcutils_allocator_t * allocator,
51+
rosidl_message_type_support_t * ts)
3552
{
3653
RCUTILS_CHECK_ARGUMENT_FOR_NULL(serialization_support, RCUTILS_RET_INVALID_ARGUMENT);
3754
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_hash, RCUTILS_RET_INVALID_ARGUMENT);
3855
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description, RCUTILS_RET_INVALID_ARGUMENT);
56+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(allocator, RCUTILS_RET_INVALID_ARGUMENT);
3957
RCUTILS_CHECK_ARGUMENT_FOR_NULL(ts, RCUTILS_RET_INVALID_ARGUMENT);
4058

4159
// NOTE(methylDragon): Not supported for now
4260
// RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description_sources, RCUTILS_RET_INVALID_ARGUMENT);
4361

4462
rcutils_ret_t ret = RCUTILS_RET_ERROR;
45-
rcutils_allocator_t allocator = rcutils_get_default_allocator();
46-
*ts = allocator.zero_allocate(1, sizeof(rosidl_message_type_support_t), allocator.state);
47-
if (!*ts) {
48-
RCUTILS_SET_ERROR_MSG("Could not allocate rosidl_message_type_support_t struct");
49-
return RCUTILS_RET_BAD_ALLOC;
50-
}
5163

52-
(*ts)->data = allocator.zero_allocate(
53-
1, sizeof(rosidl_dynamic_message_type_support_impl_t), allocator.state);
54-
if (!ts) {
64+
ts->data = allocator->zero_allocate(
65+
1, sizeof(rosidl_dynamic_message_type_support_impl_t), allocator->state);
66+
if (!ts->data) {
5567
RCUTILS_SET_ERROR_MSG("Could not allocate rosidl_dynamic_message_type_support_impl_t struct");
5668
ret = RCUTILS_RET_BAD_ALLOC;
5769
goto fail;
5870
}
5971

72+
if (rosidl_dynamic_message_type_support_impl_init(
73+
serialization_support, type_hash, type_description, type_description_sources, allocator,
74+
(rosidl_dynamic_message_type_support_impl_t *) ts->data) != RCUTILS_RET_OK)
75+
{
76+
if (rosidl_dynamic_message_type_support_impl_fini(
77+
(rosidl_dynamic_message_type_support_impl_t *) ts->data) != RCUTILS_RET_OK)
78+
{
79+
rcutils_error_string_t error_string = rcutils_get_error_string();
80+
rcutils_reset_error();
81+
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(
82+
"While handling another error, could not finalize dynamic message typesupport impl:\n%s",
83+
error_string.str);
84+
}
85+
goto fail;
86+
}
87+
88+
ts->typesupport_identifier = rosidl_dynamic_typesupport_c__identifier;
89+
ts->func = get_message_typesupport_handle_function;
90+
ts->get_type_hash_func =
91+
rosidl_get_dynamic_message_type_support_type_hash_function;
92+
ts->get_type_description_func =
93+
rosidl_get_dynamic_message_type_support_type_description_function;
94+
ts->get_type_description_sources_func =
95+
rosidl_get_dynamic_message_type_support_type_description_sources_function;
96+
97+
return RCUTILS_RET_OK;
98+
99+
fail:
100+
if (rosidl_dynamic_message_type_support_handle_fini(ts) != RCUTILS_RET_OK) {
101+
rcutils_error_string_t error_string = rcutils_get_error_string();
102+
rcutils_reset_error();
103+
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(
104+
"While handling another error, could not finalize dynamic message typesupport:\n%s",
105+
error_string.str);
106+
}
107+
return ret;
108+
}
109+
110+
rcutils_ret_t
111+
rosidl_dynamic_message_type_support_handle_fini(rosidl_message_type_support_t * ts)
112+
{
113+
if (!ts) {
114+
return RCUTILS_RET_OK;
115+
}
116+
117+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(ts->data, RCUTILS_RET_INVALID_ARGUMENT);
118+
60119
rosidl_dynamic_message_type_support_impl_t * ts_impl =
61-
(rosidl_dynamic_message_type_support_impl_t *) (*ts)->data;
120+
(rosidl_dynamic_message_type_support_impl_t *) ts->data;
121+
rcutils_allocator_t allocator = ts_impl->allocator;
122+
123+
if (ts->typesupport_identifier != rosidl_dynamic_typesupport_c__identifier) {
124+
RCUTILS_SET_ERROR_MSG("type support not from this implementation");
125+
return RCUTILS_RET_INVALID_ARGUMENT;
126+
}
127+
128+
allocator.deallocate((void *) ts->data, allocator.state);
129+
return RCUTILS_RET_OK;
130+
}
131+
132+
rcutils_ret_t
133+
rosidl_dynamic_message_type_support_impl_init(
134+
rosidl_dynamic_typesupport_serialization_support_t * serialization_support,
135+
const rosidl_type_hash_t * type_hash,
136+
const rosidl_runtime_c__type_description__TypeDescription * type_description,
137+
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources,
138+
rcutils_allocator_t * allocator,
139+
rosidl_dynamic_message_type_support_impl_t * ts_impl)
140+
{
141+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(serialization_support, RCUTILS_RET_INVALID_ARGUMENT);
142+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_hash, RCUTILS_RET_INVALID_ARGUMENT);
143+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description, RCUTILS_RET_INVALID_ARGUMENT);
144+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(allocator, RCUTILS_RET_INVALID_ARGUMENT);
145+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(ts_impl, RCUTILS_RET_INVALID_ARGUMENT);
146+
147+
// NOTE(methylDragon): Not supported for now
148+
// RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description_sources, RCUTILS_RET_INVALID_ARGUMENT);
149+
150+
rcutils_ret_t ret = RCUTILS_RET_ERROR;
62151

63152
// Copy init type hash (never null (checked above))
64-
ts_impl->type_hash = allocator.zero_allocate(1, sizeof(rosidl_type_hash_t), allocator.state);
153+
ts_impl->type_hash = allocator->zero_allocate(1, sizeof(rosidl_type_hash_t), allocator->state);
65154
if (!ts_impl->type_hash) {
66155
RCUTILS_SET_ERROR_MSG("Could not create type hash to assign into");
67156
ret = RCUTILS_RET_BAD_ALLOC;
68-
goto fail;
69157
}
70158

71159
ts_impl->type_hash->version = type_hash->version;
@@ -108,15 +196,7 @@ rosidl_dynamic_message_type_support_handle_create(
108196
}
109197

110198
ts_impl->serialization_support = serialization_support;
111-
112-
(*ts)->typesupport_identifier = rosidl_dynamic_typesupport_c__identifier;
113-
(*ts)->func = get_message_typesupport_handle_function;
114-
(*ts)->get_type_hash_func =
115-
rosidl_get_dynamic_message_type_support_type_hash_function;
116-
(*ts)->get_type_description_func =
117-
rosidl_get_dynamic_message_type_support_type_description_function;
118-
(*ts)->get_type_description_sources_func =
119-
rosidl_get_dynamic_message_type_support_type_description_sources_function;
199+
ts_impl->allocator = *allocator;
120200

121201
ret = rosidl_dynamic_typesupport_dynamic_type_create_from_description(
122202
ts_impl->serialization_support, type_description, &ts_impl->dynamic_message_type);
@@ -140,46 +220,109 @@ rosidl_dynamic_message_type_support_handle_create(
140220
return RCUTILS_RET_OK;
141221

142222
fail:
143-
if (rosidl_dynamic_message_type_support_handle_destroy(*ts) != RCUTILS_RET_OK) {
144-
RCUTILS_SAFE_FWRITE_TO_STDERR(
145-
"While handling another error, could not destroy dynamic message typesupport");
223+
if (rosidl_dynamic_message_type_support_impl_fini(ts_impl) != RCUTILS_RET_OK) {
224+
rcutils_error_string_t error_string = rcutils_get_error_string();
225+
rcutils_reset_error();
226+
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(
227+
"While handling another error, could not finalize dynamic message typesupport impl:\n%s",
228+
error_string.str);
146229
}
147230
return ret;
148231
}
149232

233+
rcutils_ret_t
234+
rosidl_dynamic_message_type_support_impl_fini(rosidl_dynamic_message_type_support_impl_t * ts_impl)
235+
{
236+
if (!ts_impl) {
237+
return RCUTILS_RET_OK;
238+
}
239+
240+
rcutils_allocator_t allocator = ts_impl->allocator;
241+
242+
if (ts_impl->type_description) {
243+
rosidl_runtime_c__type_description__TypeDescription__fini(ts_impl->type_description);
244+
}
245+
if (ts_impl->type_description_sources) {
246+
rosidl_runtime_c__type_description__TypeSource__Sequence__fini(
247+
ts_impl->type_description_sources);
248+
}
249+
if (ts_impl->dynamic_message_type) {
250+
rosidl_dynamic_typesupport_dynamic_type_destroy(ts_impl->dynamic_message_type);
251+
}
252+
if (ts_impl->dynamic_message) {
253+
rosidl_dynamic_typesupport_dynamic_data_destroy(ts_impl->dynamic_message);
254+
}
255+
allocator.deallocate(ts_impl->type_hash, allocator.state);
256+
return RCUTILS_RET_OK;
257+
}
150258

151259
rcutils_ret_t
152-
rosidl_dynamic_message_type_support_handle_destroy(rosidl_message_type_support_t * ts)
260+
rosidl_dynamic_message_type_support_handle_create(
261+
rosidl_dynamic_typesupport_serialization_support_t * serialization_support,
262+
const rosidl_type_hash_t * type_hash,
263+
const rosidl_runtime_c__type_description__TypeDescription * type_description,
264+
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources,
265+
rcutils_allocator_t * allocator,
266+
rosidl_message_type_support_t ** ts)
153267
{
268+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(serialization_support, RCUTILS_RET_INVALID_ARGUMENT);
269+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_hash, RCUTILS_RET_INVALID_ARGUMENT);
270+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description, RCUTILS_RET_INVALID_ARGUMENT);
271+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(allocator, RCUTILS_RET_INVALID_ARGUMENT);
154272
RCUTILS_CHECK_ARGUMENT_FOR_NULL(ts, RCUTILS_RET_INVALID_ARGUMENT);
155273

156-
// NOTE(methylDragon): Ignores const...
274+
// NOTE(methylDragon): Not supported for now
275+
// RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description_sources, RCUTILS_RET_INVALID_ARGUMENT);
276+
277+
rcutils_ret_t ret = RCUTILS_RET_ERROR;
278+
279+
*ts = allocator->zero_allocate(1, sizeof(rosidl_message_type_support_t), allocator->state);
280+
if (!*ts) {
281+
RCUTILS_SET_ERROR_MSG("Could not allocate rosidl_message_type_support_t struct");
282+
return RCUTILS_RET_BAD_ALLOC;
283+
}
284+
285+
ret = rosidl_dynamic_message_type_support_handle_init(
286+
serialization_support, type_hash, type_description, type_description_sources, allocator, *ts);
287+
if (ret != RCUTILS_RET_OK) {
288+
if (rosidl_dynamic_message_type_support_handle_destroy(*ts) != RCUTILS_RET_OK) {
289+
RCUTILS_SAFE_FWRITE_TO_STDERR(
290+
"While handling another error, could not destroy dynamic message typesupport");
291+
}
292+
rcutils_error_string_t error_string = rcutils_get_error_string();
293+
rcutils_reset_error();
294+
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(
295+
"Could not init dynamic message type support handle map:\n%s", error_string.str);
296+
*ts = NULL;
297+
return ret;
298+
}
299+
300+
return RCUTILS_RET_OK;
301+
}
302+
303+
rcutils_ret_t
304+
rosidl_dynamic_message_type_support_handle_destroy(rosidl_message_type_support_t * ts)
305+
{
306+
if (!ts) {
307+
return RCUTILS_RET_OK;
308+
}
309+
157310
if (ts->typesupport_identifier != rosidl_dynamic_typesupport_c__identifier) {
158311
RCUTILS_SET_ERROR_MSG("type support not from this implementation");
159312
return RCUTILS_RET_INVALID_ARGUMENT;
160313
}
161314

162-
rcutils_allocator_t allocator = rcutils_get_default_allocator();
315+
rosidl_dynamic_message_type_support_impl_t * ts_impl =
316+
(rosidl_dynamic_message_type_support_impl_t *) ts->data;
317+
rcutils_allocator_t allocator = ts_impl->allocator;
163318

164-
if (ts->data) {
165-
rosidl_dynamic_message_type_support_impl_t * ts_impl =
166-
(rosidl_dynamic_message_type_support_impl_t *)ts->data;
167-
if (ts_impl->type_description) {
168-
rosidl_runtime_c__type_description__TypeDescription__fini(ts_impl->type_description);
169-
}
170-
if (ts_impl->type_description_sources) {
171-
rosidl_runtime_c__type_description__TypeSource__Sequence__fini(
172-
ts_impl->type_description_sources);
173-
}
174-
if (ts_impl->dynamic_message_type) {
175-
rosidl_dynamic_typesupport_dynamic_type_destroy(ts_impl->dynamic_message_type);
176-
}
177-
if (ts_impl->dynamic_message) {
178-
rosidl_dynamic_typesupport_dynamic_data_destroy(ts_impl->dynamic_message);
179-
}
180-
allocator.deallocate(ts_impl->type_hash, allocator.state);
319+
if (rosidl_dynamic_message_type_support_handle_fini(ts) != RCUTILS_RET_OK) {
320+
rcutils_error_string_t error_string = rcutils_get_error_string();
321+
rcutils_reset_error();
322+
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(
323+
"Could not finalize dynamic message typesupport:\n%s", error_string.str);
181324
}
182-
allocator.deallocate((void *)ts->data, allocator.state);
325+
183326
allocator.deallocate(ts, allocator.state);
184327
return RCUTILS_RET_OK;
185328
}

0 commit comments

Comments
 (0)