Creating and destroying JSON objects may be time consuming. Add yielding counterparts of json_serialized_object_create() and json_destroy__() functions that make use of the cooperative multitasking module to yield during processing, allowing time sensitive tasks in other parts of the program to be completed during processing.
Signed-off-by: Frode Nordahl <[email protected]> --- include/openvswitch/json.h | 16 ++++++++-- lib/json.c | 63 ++++++++++++++++++++++++++------------ 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/include/openvswitch/json.h b/include/openvswitch/json.h index 35b403c29..39528f140 100644 --- a/include/openvswitch/json.h +++ b/include/openvswitch/json.h @@ -81,6 +81,7 @@ struct json *json_boolean_create(bool); struct json *json_string_create(const char *); struct json *json_string_create_nocopy(char *); struct json *json_serialized_object_create(const struct json *); +struct json *json_serialized_object_create_with_yield(const struct json *); struct json *json_integer_create(long long int); struct json *json_real_create(double); @@ -137,7 +138,8 @@ struct json *json_from_stream(FILE *stream); enum { JSSF_PRETTY = 1 << 0, /* Multiple lines with indentation, if true. */ - JSSF_SORT = 1 << 1 /* Object members in sorted order, if true. */ + JSSF_SORT = 1 << 1, /* Object members in sorted order, if true. */ + JSSF_YIELD = 1 << 2 /* Yield during processing */ }; char *json_to_string(const struct json *, int flags); void json_to_ds(const struct json *, int flags, struct ds *); @@ -158,14 +160,22 @@ json_clone(const struct json *json_) return json; } -void json_destroy__(struct json *json); +void json_destroy__(struct json *json, bool yield); /* Frees 'json' and everything it points to, recursively. */ static inline void json_destroy(struct json *json) { if (json && !--json->count) { - json_destroy__(json); + json_destroy__(json, false); + } +} + +static inline void +json_destroy_with_yield(struct json *json) +{ + if (json && !--json->count) { + json_destroy__(json, true); } } diff --git a/lib/json.c b/lib/json.c index aded8bb01..78ebabb18 100644 --- a/lib/json.c +++ b/lib/json.c @@ -24,6 +24,7 @@ #include <limits.h> #include <string.h> +#include "cooperative-multitasking.h" #include "openvswitch/dynamic-string.h" #include "hash.h" #include "openvswitch/shash.h" @@ -181,14 +182,26 @@ json_string_create(const char *s) return json_string_create_nocopy(xstrdup(s)); } -struct json * -json_serialized_object_create(const struct json *src) +static struct json * +json_serialized_object_create__(const struct json *src, int flags) { struct json *json = json_create(JSON_SERIALIZED_OBJECT); - json->string = json_to_string(src, JSSF_SORT); + json->string = json_to_string(src, flags); return json; } +struct json * +json_serialized_object_create(const struct json *src) +{ + return json_serialized_object_create__(src, JSSF_SORT); +} + +struct json * +json_serialized_object_create_with_yield(const struct json *src) +{ + return json_serialized_object_create__(src, JSSF_SORT | JSSF_YIELD); +} + struct json * json_array_create_empty(void) { @@ -360,20 +373,20 @@ json_integer(const struct json *json) return json->integer; } -static void json_destroy_object(struct shash *object); -static void json_destroy_array(struct json_array *array); +static void json_destroy_object(struct shash *object, bool yield); +static void json_destroy_array(struct json_array *array, bool yield); /* Frees 'json' and everything it points to, recursively. */ void -json_destroy__(struct json *json) +json_destroy__(struct json *json, bool yield) { switch (json->type) { case JSON_OBJECT: - json_destroy_object(json->object); + json_destroy_object(json->object, yield); break; case JSON_ARRAY: - json_destroy_array(&json->array); + json_destroy_array(&json->array, yield); break; case JSON_STRING: @@ -395,13 +408,16 @@ json_destroy__(struct json *json) } static void -json_destroy_object(struct shash *object) +json_destroy_object(struct shash *object, bool yield) { struct shash_node *node; SHASH_FOR_EACH_SAFE (node, object) { struct json *value = node->data; + if (yield) { + cooperative_multitasking_yield(); + } json_destroy(value); shash_delete(object, node); } @@ -410,12 +426,13 @@ json_destroy_object(struct shash *object) } static void -json_destroy_array(struct json_array *array) +json_destroy_array(struct json_array *array, bool yield) { size_t i; for (i = 0; i < array->n; i++) { - json_destroy(array->elems[i]); + yield ? json_destroy_with_yield(array->elems[i]) : + json_destroy(array->elems[i]); } free(array->elems); } @@ -1525,7 +1542,7 @@ static void json_serialize_object(const struct shash *object, struct json_serializer *); static void json_serialize_array(const struct json_array *, struct json_serializer *); -static void json_serialize_string(const char *, struct ds *); +static void json_serialize_string(const char *, struct json_serializer *); /* Converts 'json' to a string in JSON format, encoded in UTF-8, and returns * that string. The caller is responsible for freeing the returned string, @@ -1598,7 +1615,7 @@ json_serialize(const struct json *json, struct json_serializer *s) break; case JSON_STRING: - json_serialize_string(json->string, ds); + json_serialize_string(json->string, s); break; case JSON_SERIALIZED_OBJECT: @@ -1631,7 +1648,7 @@ json_serialize_object_member(size_t i, const struct shash_node *node, indent_line(s); } - json_serialize_string(node->name, ds); + json_serialize_string(node->name, s); ds_put_char(ds, ':'); if (s->flags & JSSF_PRETTY) { ds_put_char(ds, ' '); @@ -1734,7 +1751,7 @@ static const char *chars_escaping[256] = { }; static void -json_serialize_string(const char *string, struct ds *ds) +json_serialize_string(const char *string, struct json_serializer *s) { uint8_t c; uint8_t c2; @@ -1742,26 +1759,32 @@ json_serialize_string(const char *string, struct ds *ds) const char *escape; const char *start; - ds_put_char(ds, '"'); + ds_put_char(s->ds, '"'); count = 0; start = string; while ((c = *string++) != '\0') { + if (s->flags & JSSF_YIELD) { + cooperative_multitasking_yield(); + } if (c >= ' ' && c != '"' && c != '\\') { count++; } else { if (count) { - ds_put_buffer(ds, start, count); + ds_put_buffer(s->ds, start, count); count = 0; } start = string; escape = chars_escaping[c]; while ((c2 = *escape++) != '\0') { - ds_put_char(ds, c2); + if (s->flags & JSSF_YIELD) { + cooperative_multitasking_yield(); + } + ds_put_char(s->ds, c2); } } } if (count) { - ds_put_buffer(ds, start, count); + ds_put_buffer(s->ds, start, count); } - ds_put_char(ds, '"'); + ds_put_char(s->ds, '"'); } -- 2.34.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
