Browse Source

Merge pull request #2 from json-c/master

merge upstream
tags/json-c-0.13-20171207
Haffon GitHub 8 years ago
parent
commit
86a3a6475f
7 changed files with 131 additions and 26 deletions
  1. +34
    -4
      Makefile.am
  2. +20
    -1
      README.md
  3. +2
    -0
      arraylist.c
  4. +1
    -1
      autogen.sh
  5. +41
    -1
      configure.ac
  6. +30
    -18
      json_object.c
  7. +3
    -1
      json_util.c

+ 34
- 4
Makefile.am View File

@@ -56,13 +56,43 @@ libjson_c_la_SOURCES = \
strerror_override.c \
strerror_override_private.h


DISTCLEANFILES=
DISTCLEANFILES+= \
config.h \
json-c-uninstalled.pc \
json-c.pc \
json_config.h

distclean-local:
-rm -rf $(testsubdir)
-rm -rf config.h.in~ Makefile.in aclocal.m4 autom4te.cache/ config.guess config.sub depcomp install-sh ltmain.sh missing
-rm -f INSTALL test-driver tests/Makefile.in compile

maintainer-clean-local:
-rm -rf configure
JSON_CLEANFILES=
JSON_CLEANFILES+= \
Makefile.in \
aclocal.m4 \
autom4te.cache/ \
compile \
config.guess \
config.h.in \
config.sub \
configure \
depcomp \
install-sh \
ltmain.sh \
missing \
test-driver \
tests/Makefile.in
JSON_CLEANFILES+= \
libtool \
stamp-h1 \
stamp-h2

# There's no built-in way to remove these after all the other
# maintainer-clean steps happen, so do it explicitly here.
really-clean:
$(MAKE) maintainer-clean
rm -rf ${JSON_CLEANFILES}

uninstall-local:
rm -rf "$(DESTDIR)@includedir@/json-c"


+ 20
- 1
README.md View File

@@ -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`
----------------------



+ 2
- 0
arraylist.c View File

@@ -22,6 +22,7 @@
# include <strings.h>
#endif /* HAVE_STRINGS_H */

#ifndef SIZE_T_MAX
#if SIZEOF_SIZE_T == SIZEOF_INT
#define SIZE_T_MAX UINT_MAX
#elif SIZEOF_SIZE_T == SIZEOF_LONG
@@ -31,6 +32,7 @@
#else
#error Unable to determine size of size_t
#endif
#endif

#include "arraylist.h"



+ 1
- 1
autogen.sh View File

@@ -1,5 +1,5 @@
#!/bin/sh
autoreconf -Iautoconf-archive/m4 -v --install || exit 1
autoreconf -v --install || exit 1

# If there are any options, assume the user wants to run configure.
# To run configure w/o any options, use ./autogen.sh --configure


+ 41
- 1
configure.ac View File

@@ -5,16 +5,32 @@ AC_INIT([json-c], 0.12.99, [json-c@googlegroups.com])

AM_INIT_AUTOMAKE

AC_CONFIG_MACRO_DIRS([autoconf-archive/m4])

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
@@ -66,6 +82,30 @@ AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]])
AC_CHECK_DECLS([_finite], [], [], [[#include <float.h>]])
AC_MSG_CHECKING(for GCC atomic builtins)
AC_LINK_IFELSE(
[
AC_LANG_SOURCE([[
int main() {
volatile unsigned int val = 1;
/* Note: __sync_val_compare_and_swap isn't checked here
* because it's protected by __GCC_HAVE_SYNC_COMPARE_AND_SWAP_<n>,
* which is automatically defined by gcc.
*/
__sync_add_and_fetch(&val, 1);
__sync_sub_and_fetch(&val, 1);
return 0;
}
]])
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_ATOMIC_BUILTINS],[1],[Has atomic builtins])
],
[
AC_MSG_RESULT([no])
AC_MSG_WARN([json-c will be built without atomic refcounts because atomic builtins are missing])
])

case "${host_os}" in
linux*)


+ 30
- 18
json_object.c View File

@@ -163,25 +163,37 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl

extern struct json_object* json_object_retain(struct json_object *jso)
{
if (jso)
jso->_ref_count++;
if (!jso) return jso;

#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
__sync_add_and_fetch(&jso->_ref_count, 1);
#else
++jso->_ref_count;
#endif

return jso;
}

int json_object_release(struct json_object *jso)
{
if(jso)
{
jso->_ref_count--;
if(!jso->_ref_count)
{
if (jso->_user_delete)
jso->_user_delete(jso, jso->_userdata);
jso->_delete(jso);
return 1;
}
}
return 0;
if(!jso) return 0;

#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,
* as that can result in the thread that loses the race to 0
* operating on an already-freed object.
*/
if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) return 0;
#else
if (--jso->_ref_count > 0) return 0;
#endif

if (jso->_user_delete)
jso->_user_delete(jso, jso->_userdata);
jso->_delete(jso);
return 1;
}


@@ -693,7 +705,7 @@ int json_object_set_int64(struct json_object *jso,int64_t new_value){

/* json_object_double */

#ifdef HAVE___THREAD
#if defined(HAVE___THREAD)
// i.e. __thread or __declspec(thread)
static SPEC___THREAD char *tls_serialization_float_format = NULL;
#endif
@@ -703,7 +715,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)
if (tls_serialization_float_format)
{
free(tls_serialization_float_format);
@@ -716,7 +728,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)
if (tls_serialization_float_format)
{
free(tls_serialization_float_format);
@@ -765,7 +777,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)
if (tls_serialization_float_format)
std_format = tls_serialization_float_format;
else


+ 3
- 1
json_util.c View File

@@ -265,7 +265,9 @@ int json_parse_int64(const char *buf, int64_t *retval)
// Skip leading zeros, but keep at least one digit
while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
buf_sig_digits++;
if (num64 == 0) // assume all sscanf impl's will parse -0 to 0
// Can't check num64==0 because some sscanf impl's parse
// non-zero values to 0. (e.g. Illumos with UINT64_MAX)
if (buf_sig_digits[0] == '0' && buf_sig_digits[1] == '\0')
orig_has_neg = 0; // "-0" is the same as just plain "0"

snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);


Loading…
Cancel
Save