From 2d1da5ab13463dc52c9e8d262cb51b80c7376ebb Mon Sep 17 00:00:00 2001 From: Eric Haszlakiewicz <erh+git@nimenees.com> Date: Sun, 3 Sep 2017 23:37:12 -0400 Subject: [PATCH] Add a --enable-threading configure option, and only use the (slower) __sync_add_and_fetch()/__sync_sub_and_fetch() function when it is specified. --- README.md | 21 ++++++++++++++++++++- configure.ac | 16 +++++++++++++++- json_object.c | 12 ++++++------ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0e87cd5..bddcff7 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ $ sh autogen.sh followed by ```sh -$ ./configure +$ ./configure # --enable-threading $ make $ make install ``` @@ -56,6 +56,25 @@ To build and run the test programs: $ make check ``` +Building with partial threading support +---------------------------------------- + +Although json-c does not support fully multi-threaded access to +object trees, it has some code to help make use in threaded programs +a bit safer. Currently, this is limited to using atomic operations for +json_object_get() and json_object_put(). + +Since this may have a performance impact, of at least 3x slower +according to https://stackoverflow.com/a/11609063, it is disabled by +default. You may turn it on by adjusting your configure command with: + --enable-threading + +Separately, the default hash function used for object field keys, +lh_char_hash, uses a compare-and-swap operation to ensure the randomly +seed is only generated once. Because this is a one-time operation, it +is always compiled in when the compare-and-swap operation is available. + + Linking to `libjson-c` ---------------------- diff --git a/configure.ac b/configure.ac index e909cf2..0ebf823 100644 --- a/configure.ac +++ b/configure.ac @@ -11,12 +11,26 @@ AC_PROG_MAKE_SET AC_CANONICAL_HOST +AC_ARG_ENABLE(threading, + AS_HELP_STRING([--enable-threading], + [Enable code to support partly multi-threaded use]), +[if test x$enableval = xyes; then + enable_threading=yes + AC_DEFINE(ENABLE_THREADING, 1, [Enable partial threading support]) +fi]) + +if test "x$enable_threading" = "xyes"; then + AC_MSG_RESULT([Partial multi-threaded support enabled.]) +else + AC_MSG_RESULT([Multi-threaded support disabled. Use --enable-threading to enable.]) +fi + AC_ARG_ENABLE(rdrand, AS_HELP_STRING([--enable-rdrand], [Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]), [if test x$enableval = xyes; then enable_rdrand=yes - AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed]) + AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRAND Hardware RNG Hash Seed]) fi]) if test "x$enable_rdrand" = "xyes"; then diff --git a/json_object.c b/json_object.c index c09d61d..fcda69f 100644 --- a/json_object.c +++ b/json_object.c @@ -165,7 +165,7 @@ extern struct json_object* json_object_get(struct json_object *jso) { if (!jso) return jso; -#ifdef HAVE_ATOMIC_BUILTINS +#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING) __sync_add_and_fetch(&jso->_ref_count, 1); #else ++jso->_ref_count; @@ -178,7 +178,7 @@ int json_object_put(struct json_object *jso) { if(!jso) return 0; -#ifdef HAVE_ATOMIC_BUILTINS +#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING) /* Note: this only allow the refcount to remain correct * when multiple threads are adjusting it. It is still an error * for a thread to decrement the refcount if it doesn't "own" it, @@ -703,7 +703,7 @@ int json_object_set_int64(struct json_object *jso,int64_t new_value){ /* json_object_double */ -#ifdef HAVE___THREAD +#if defined(HAVE___THREAD) && defined(ENABLE_THREADING) // i.e. __thread or __declspec(thread) static SPEC___THREAD char *tls_serialization_float_format = NULL; #endif @@ -713,7 +713,7 @@ int json_c_set_serialization_double_format(const char *double_format, int global { if (global_or_thread == JSON_C_OPTION_GLOBAL) { -#ifdef HAVE___THREAD +#if defined(HAVE___THREAD) && defined(ENABLE_THREADING) if (tls_serialization_float_format) { free(tls_serialization_float_format); @@ -726,7 +726,7 @@ int json_c_set_serialization_double_format(const char *double_format, int global } else if (global_or_thread == JSON_C_OPTION_THREAD) { -#ifdef HAVE___THREAD +#if defined(HAVE___THREAD) && defined(ENABLE_THREADING) if (tls_serialization_float_format) { free(tls_serialization_float_format); @@ -775,7 +775,7 @@ static int json_object_double_to_json_string_format(struct json_object* jso, { const char *std_format = "%.17g"; -#ifdef HAVE___THREAD +#if defined(HAVE___THREAD) && defined(ENABLE_THREADING) if (tls_serialization_float_format) std_format = tls_serialization_float_format; else -- 2.40.0