You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dc...@apache.org on 2012/05/20 16:24:20 UTC

svn commit: r1340735 - in /avro/trunk: CHANGES.txt lang/c/CMakeLists.txt lang/c/INSTALL lang/c/README.maintaining_win32.txt lang/c/src/CMakeLists.txt lang/c/src/errors.c

Author: dcreager
Date: Sun May 20 14:24:19 2012
New Revision: 1340735

URL: http://svn.apache.org/viewvc?rev=1340735&view=rev
Log:
AVRO-1092. C: Thread-safe versions of error handling code.

We now provide optional thread-safe versions of the error managing code
on Unix.  (Only on Unix for now, because we rely on pthread's
thread-local storage API.)  You can ask for thread-safe versions by
defining the THREADSAFE cmake variable.

Contributed by Pugachev Maxim; Windows compatibility added by Vivek
Nadkarni.

Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/c/CMakeLists.txt
    avro/trunk/lang/c/INSTALL
    avro/trunk/lang/c/README.maintaining_win32.txt
    avro/trunk/lang/c/src/CMakeLists.txt
    avro/trunk/lang/c/src/errors.c

Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1340735&r1=1340734&r2=1340735&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Sun May 20 14:24:19 2012
@@ -104,6 +104,9 @@ Avro 1.7.0 (unreleased)
     AVRO-1088. C: Performance tests for arrays and schema resolution.
     (Vivek Nadkarni via dcreager)
 
+    AVRO-1092. C: Error management code can be defined in a thread-safe
+    manner.  (Pugachev Maxim and Vivek Nadkarni via dcreager)
+
 Avro 1.6.3 (5 March 2012)
 
     AVRO-1077. Missing 'inline' for union set function. (thiru)

Modified: avro/trunk/lang/c/CMakeLists.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/CMakeLists.txt?rev=1340735&r1=1340734&r2=1340735&view=diff
==============================================================================
--- avro/trunk/lang/c/CMakeLists.txt (original)
+++ avro/trunk/lang/c/CMakeLists.txt Sun May 20 14:24:19 2012
@@ -106,6 +106,20 @@ endif(WIN32)
 # Uncomment to allow non-atomic increment/decrement of reference count
 # add_definitions(-DAVRO_ALLOW_NON_ATOMIC_REFCOUNT)
 
+# Thread support (only for *nix with pthreads)
+set(THREADS_LIBRARIES)
+if(UNIX AND THREADSAFE AND CMAKE_COMPILER_IS_GNUCC)
+    set(CMAKE_THREAD_PREFER_PTHREAD)
+    find_package(Threads)
+
+    if(NOT CMAKE_USE_PTHREADS_INIT)
+        message(FATAL_ERROR "pthreads not found")
+    endif(NOT CMAKE_USE_PTHREADS_INIT)
+
+    add_definitions(-DTHREADSAFE -D_REENTRANT)
+    set(THREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+endif(UNIX AND THREADSAFE AND CMAKE_COMPILER_IS_GNUCC)
+
 include_directories(${AvroC_SOURCE_DIR}/src)
 include_directories(${AvroC_SOURCE_DIR}/jansson/src)
 

Modified: avro/trunk/lang/c/INSTALL
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/INSTALL?rev=1340735&r1=1340734&r2=1340735&view=diff
==============================================================================
--- avro/trunk/lang/c/INSTALL (original)
+++ avro/trunk/lang/c/INSTALL Sun May 20 14:24:19 2012
@@ -55,3 +55,9 @@ like the following:
 to the cmake command given above.  The set of architectures that you can
 choose from differs depending on which version of OS X you're running;
 common possibilities include "i386", "x86_64", "ppc", and "ppc64".
+
+On Unix, you can request thread-safe versions of the Avro library's
+global functions by defining the THREADSAFE cmake variable.  Just add
+the following to your cmake invokation:
+
+        -DTHREADSAFE=true

Modified: avro/trunk/lang/c/README.maintaining_win32.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/README.maintaining_win32.txt?rev=1340735&r1=1340734&r2=1340735&view=diff
==============================================================================
--- avro/trunk/lang/c/README.maintaining_win32.txt (original)
+++ avro/trunk/lang/c/README.maintaining_win32.txt Sun May 20 14:24:19 2012
@@ -152,3 +152,15 @@ Instructions for Maintenance
     changes in st.c and st.h -- which were converted to new-style
     function declarations.
 
+19. Structures cannot be initialized using the .element notation for
+    Win32. For example if we have a struct test_t:
+        typedef struct
+        {
+           int a;
+           int b;
+        } test_t;
+    Then we can initialize the struct using the syntax:
+        test_t t1 = { 0, 0 };
+    But we cannot use the syntax:
+        test_t t2 = { .a = 0, . b = 0 };
+    because Win32 does not support it.

Modified: avro/trunk/lang/c/src/CMakeLists.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/CMakeLists.txt?rev=1340735&r1=1340734&r2=1340735&view=diff
==============================================================================
--- avro/trunk/lang/c/src/CMakeLists.txt (original)
+++ avro/trunk/lang/c/src/CMakeLists.txt Sun May 20 14:24:19 2012
@@ -102,13 +102,13 @@ source_group(Jansson FILES ${JANSSON_SRC
 string(REPLACE ":" "." LIBAVRO_DOT_VERSION ${LIBAVRO_VERSION})
 
 add_library(avro-static STATIC ${AVRO_SRC} ${JANSSON_SRC})
-target_link_libraries(avro-static ${CODEC_LIBRARIES})
+target_link_libraries(avro-static ${CODEC_LIBRARIES} ${THREADS_LIBRARIES})
 set_target_properties(avro-static PROPERTIES OUTPUT_NAME avro)
 
 if (NOT WIN32)
 # TODO: Create Windows DLLs. See http://www.cmake.org/Wiki/BuildingWinDLL
 add_library(avro-shared SHARED ${AVRO_SRC} ${JANSSON_SRC})
-target_link_libraries(avro-shared ${CODEC_LIBRARIES})
+target_link_libraries(avro-shared ${CODEC_LIBRARIES} ${THREADS_LIBRARIES})
 set_target_properties(avro-shared PROPERTIES
         OUTPUT_NAME avro
         SOVERSION ${LIBAVRO_DOT_VERSION})

Modified: avro/trunk/lang/c/src/errors.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/errors.c?rev=1340735&r1=1340734&r2=1340735&view=diff
==============================================================================
--- avro/trunk/lang/c/src/errors.c (original)
+++ avro/trunk/lang/c/src/errors.c Sun May 20 14:24:19 2012
@@ -18,9 +18,21 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "avro/errors.h"
 
+#if defined THREADSAFE && (defined __unix__ || defined __unix)
+#include <pthread.h>
+static pthread_key_t error_data_key;
+static pthread_once_t error_data_key_once = PTHREAD_ONCE_INIT;
+
+static void make_error_data_key()
+{
+    pthread_key_create(&error_data_key, free);
+}
+#endif
+
 /* 4K should be enough, right? */
 #define AVRO_ERROR_SIZE 4096
 
@@ -31,11 +43,46 @@
  * buffer, and then swaps them.
  */
 
-static char  AVRO_ERROR1[AVRO_ERROR_SIZE] = {'\0'};
-static char  AVRO_ERROR2[AVRO_ERROR_SIZE] = {'\0'};
+struct avro_error_data_t {
+    char  AVRO_ERROR1[AVRO_ERROR_SIZE];
+    char  AVRO_ERROR2[AVRO_ERROR_SIZE];
+
+    char  *AVRO_CURRENT_ERROR;
+    char  *AVRO_OTHER_ERROR;
+};
+
 
-static char  *AVRO_CURRENT_ERROR = AVRO_ERROR1;
-static char  *AVRO_OTHER_ERROR = AVRO_ERROR2;
+static struct avro_error_data_t *
+avro_get_error_data(void)
+{
+#if defined THREADSAFE && (defined __unix__ || defined __unix)
+    pthread_once(&error_data_key_once, make_error_data_key);
+
+    struct avro_error_data_t *ERROR_DATA =
+        (struct avro_error_data_t*) pthread_getspecific(error_data_key);
+
+    if (!ERROR_DATA) {
+        ERROR_DATA = (struct avro_error_data_t*) malloc(sizeof(struct avro_error_data_t));
+        pthread_setspecific(error_data_key, ERROR_DATA);
+
+        ERROR_DATA->AVRO_ERROR1[0] = '\0';
+        ERROR_DATA->AVRO_ERROR2[0] = '\0';
+        ERROR_DATA->AVRO_CURRENT_ERROR = ERROR_DATA->AVRO_ERROR1;
+        ERROR_DATA->AVRO_OTHER_ERROR = ERROR_DATA->AVRO_ERROR2;
+    }
+
+    return ERROR_DATA;
+#else
+    static struct avro_error_data_t ERROR_DATA = {
+      /* .AVRO_ERROR1 = */ {'\0'},
+      /* .AVRO_ERROR2 = */ {'\0'},
+      /* .AVRO_CURRENT_ERROR = */ ERROR_DATA.AVRO_ERROR1,
+      /* .AVRO_OTHER_ERROR = */ ERROR_DATA.AVRO_ERROR2,
+    };
+
+    return &ERROR_DATA;
+#endif
+}
 
 
 void
@@ -43,7 +90,7 @@ avro_set_error(const char *fmt, ...)
 {
 	va_list  args;
 	va_start(args, fmt);
-	vsnprintf(AVRO_CURRENT_ERROR, AVRO_ERROR_SIZE, fmt, args);
+	vsnprintf(avro_get_error_data()->AVRO_CURRENT_ERROR, AVRO_ERROR_SIZE, fmt, args);
 	va_end(args);
 	//fprintf(stderr, "--- %s\n", AVRO_CURRENT_ERROR);
 }
@@ -52,13 +99,15 @@ avro_set_error(const char *fmt, ...)
 void
 avro_prefix_error(const char *fmt, ...)
 {
+    struct avro_error_data_t *ERROR_DATA = avro_get_error_data();
+
 	/*
 	 * First render the prefix into OTHER_ERROR.
 	 */
 
 	va_list  args;
 	va_start(args, fmt);
-	int  bytes_written = vsnprintf(AVRO_OTHER_ERROR, AVRO_ERROR_SIZE, fmt, args);
+	int  bytes_written = vsnprintf(ERROR_DATA->AVRO_OTHER_ERROR, AVRO_ERROR_SIZE, fmt, args);
 	va_end(args);
 
 	/*
@@ -66,9 +115,9 @@ avro_prefix_error(const char *fmt, ...)
 	 */
 
 	if (bytes_written < AVRO_ERROR_SIZE) {
-		strncpy(&AVRO_OTHER_ERROR[bytes_written], AVRO_CURRENT_ERROR,
+		strncpy(&ERROR_DATA->AVRO_OTHER_ERROR[bytes_written], ERROR_DATA->AVRO_CURRENT_ERROR,
 			AVRO_ERROR_SIZE - bytes_written);
-		AVRO_OTHER_ERROR[AVRO_ERROR_SIZE-1] = '\0';
+		ERROR_DATA->AVRO_OTHER_ERROR[AVRO_ERROR_SIZE-1] = '\0';
 	}
 
 	/*
@@ -76,14 +125,14 @@ avro_prefix_error(const char *fmt, ...)
 	 */
 
 	char  *tmp;
-	tmp = AVRO_OTHER_ERROR;
-	AVRO_OTHER_ERROR = AVRO_CURRENT_ERROR;
-	AVRO_CURRENT_ERROR = tmp;
+	tmp = ERROR_DATA->AVRO_OTHER_ERROR;
+	ERROR_DATA->AVRO_OTHER_ERROR = ERROR_DATA->AVRO_CURRENT_ERROR;
+	ERROR_DATA->AVRO_CURRENT_ERROR = tmp;
 	//fprintf(stderr, "+++ %s\n", AVRO_CURRENT_ERROR);
 }
 
 
 const char *avro_strerror(void)
 {
-	return AVRO_CURRENT_ERROR;
+	return avro_get_error_data()->AVRO_CURRENT_ERROR;
 }