Commit 3decba7a authored by Robert Edmonds's avatar Robert Edmonds

remove protobuf_c_default_allocator

"protobuf_c_default_allocator" is the last bit of global data in
libprotobuf-c, and it can be hidden with some relatively easy (though
API/ABI-breaking) changes to ProtobufCBufferSimple.

all exported functions that take a ProtobufCAllocator either use the
provided allocator (if non-NULL), or switch to the default allocator (if
NULL). there are now two relatively unambiguous choices when a
ProtobufCAllocator is required by an exported function:

    1) use NULL. the vast majority of callers should pick this option.

    2) implement your own allocation functions, and enclose these in a
    ProtobufCAllocator struct.

in previous versions of protobuf-c there were two other possibilities:

    3) maybe use &protobuf_c_system_allocator?

    4) maybe use &protobuf_c_default_allocator?

this was relatively confusing, and by removing these latter two options
we can avoid having global library state.
parent 17d26c0a
LIBPROTOBUF_C_1.0.0 {
global:
protobuf_c_buffer_simple_append;
protobuf_c_default_allocator;
protobuf_c_enum_descriptor_get_value;
protobuf_c_enum_descriptor_get_value_by_name;
protobuf_c_message_check;
......
......@@ -164,11 +164,11 @@ do_free(ProtobufCAllocator *allocator, void *data)
}
/*
* Some users may configure the default allocator; providing your own allocator
* to unpack() is preferred. This allocator is still used for packing nested
* messages.
* This allocator uses the system's malloc() and free(). It is the default
* allocator used if NULL is passed as the ProtobufCAllocator to an exported
* function.
*/
ProtobufCAllocator protobuf_c_default_allocator = {
static ProtobufCAllocator protobuf_c__allocator = {
.alloc = &system_alloc,
.free = &system_free,
.allocator_data = NULL,
......@@ -184,16 +184,20 @@ protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
size_t new_len = simp->len + len;
if (new_len > simp->alloced) {
ProtobufCAllocator *allocator = simp->allocator;
size_t new_alloced = simp->alloced * 2;
uint8_t *new_data;
if (allocator == NULL)
allocator = &protobuf_c__allocator;
while (new_alloced < new_len)
new_alloced += new_alloced;
new_data = do_alloc(&protobuf_c_default_allocator, new_alloced);
new_data = do_alloc(allocator, new_alloced);
if (!new_data)
return;
memcpy(new_data, simp->data, simp->len);
if (simp->must_free_data)
do_free(&protobuf_c_default_allocator, simp->data);
do_free(allocator, simp->data);
else
simp->must_free_data = TRUE;
simp->data = new_data;
......@@ -2692,7 +2696,7 @@ protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
if (allocator == NULL)
allocator = &protobuf_c_default_allocator;
allocator = &protobuf_c__allocator;
rv = do_alloc(allocator, desc->sizeof_message);
if (!rv)
......@@ -2960,7 +2964,7 @@ protobuf_c_message_free_unpacked(ProtobufCMessage *message,
ASSERT_IS_MESSAGE(message);
if (allocator == NULL)
allocator = &protobuf_c_default_allocator;
allocator = &protobuf_c__allocator;
message->descriptor = NULL;
for (f = 0; f < desc->n_fields; f++) {
if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
......
......@@ -458,6 +458,8 @@ struct ProtobufCBufferSimple {
uint8_t *data;
/** Whether `data` must be freed. */
protobuf_c_boolean must_free_data;
/** Allocator to use. May be NULL to indicate the system allocator. */
ProtobufCAllocator *allocator;
};
/**
......@@ -736,17 +738,6 @@ struct ProtobufCServiceDescriptor {
const unsigned *method_indices_by_name;
};
/**
* The default memory allocator.
*
* By default, it uses the system allocator (meaning malloc() and free()).
* This is typically changed to adapt to frameworks that provide
* some non-standard allocation functions.
*
* NOTE: you may modify this allocator.
*/
extern PROTOBUF_C__API ProtobufCAllocator protobuf_c_default_allocator;
/**
* Get the version of the protobuf-c library. Note that this is the version of
* the library linked against, not the version of the headers compiled against.
......@@ -1028,7 +1019,8 @@ protobuf_c_service_descriptor_get_method_by_name(
sizeof(array_of_bytes), \
0, \
(array_of_bytes), \
0 \
0, \
NULL \
}
/**
......@@ -1037,9 +1029,12 @@ protobuf_c_service_descriptor_get_method_by_name(
#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
do { \
if ((simp_buf)->must_free_data) { \
protobuf_c_default_allocator.free( \
&protobuf_c_default_allocator, \
if ((simp_buf)->allocator != NULL) \
(simp_buf)->allocator->free( \
(simp_buf)->allocator, \
(simp_buf)->data); \
else \
free((simp_buf)->data); \
} \
} while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment