Re: [xml] per thread globals initialization patch



Daniel Veillard wrote:

 Hum, the definitions for xmlInitGlobals() and xmlCleanupGlobals()
seems to be missing , could you send these so I can commit :-)

Daniel

Ooops, sorry. Forgot to include globals.c in the patch...

Here it is, along with the python test case.

-sbi
Index: globals.c
===================================================================
RCS file: /cvs/gnome/gnome-xml/globals.c,v
retrieving revision 1.23
diff -c -b -r1.23 globals.c
*** globals.c   21 Apr 2003 21:36:39 -0000      1.23
--- globals.c   15 May 2003 20:11:14 -0000
***************
*** 21,26 ****
--- 21,27 ----
  
  #include <libxml/globals.h>
  #include <libxml/xmlmemory.h>
+ #include <libxml/threads.h>
  
  /* #define DEBUG_GLOBALS */
  
***************
*** 33,38 ****
--- 34,54 ----
  #define IS_MAIN_THREAD 1
  #endif
  
+ /*
+  * Mutex to protect "ForNewThreads" variables
+  */
+ static xmlMutexPtr xmlThrDefMutex = NULL;
+ 
+ void xmlInitGlobals()
+ {
+     xmlThrDefMutex = xmlNewMutex();
+ }
+ 
+ void xmlCleanupGlobals()
+ {
+     xmlFreeMutex(xmlThrDefMutex);
+ }
+ 
  /************************************************************************
   *                                                                    *
   *    All the user accessible global variables of the library         *
***************
*** 150,161 ****
--- 166,179 ----
   * XML_BUFFER_ALLOC_EXACT
   */
  xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
+ static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT;
  /**
   * xmlDefaultBufferSize:
   *
   * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
   */
  int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
+ static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
  
  /*
   * Parser defaults
***************
*** 175,180 ****
--- 193,199 ----
   * Disabled by default
   */
  int xmlParserDebugEntities = 0;
+ static int xmlParserDebugEntitiesThrDef = 0;
  /**
   * xmlDoValidityCheckingDefaultValue:
   *
***************
*** 182,187 ****
--- 201,207 ----
   * Disabled by default.
   */
  int xmlDoValidityCheckingDefaultValue = 0;
+ static int xmlDoValidityCheckingDefaultValueThrDef = 0;
  /**
   * xmlGetWarningsDefaultValue:
   *
***************
*** 189,194 ****
--- 209,215 ----
   * Activated by default.
   */
  int xmlGetWarningsDefaultValue = 1;
+ static int xmlGetWarningsDefaultValueThrDef = 1;
  /**
   * xmlLoadExtDtdDefaultValue:
   *
***************
*** 197,202 ****
--- 218,224 ----
   * Disabled by default.
   */
  int xmlLoadExtDtdDefaultValue = 0;
+ static int xmlLoadExtDtdDefaultValueThrDef = 0;
  /**
   * xmlPedanticParserDefaultValue:
   *
***************
*** 204,209 ****
--- 226,232 ----
   * Disabled by default.
   */
  int xmlPedanticParserDefaultValue = 0;
+ static int xmlPedanticParserDefaultValueThrDef = 0;
  /**
   * xmlLineNumbersDefaultValue:
   *
***************
*** 213,218 ****
--- 236,242 ----
   * applicaton.
   */
  int xmlLineNumbersDefaultValue = 0;
+ static int xmlLineNumbersDefaultValueThrDef = 0;
  /**
   * xmlKeepBlanksDefaultValue:
   *
***************
*** 223,228 ****
--- 247,253 ----
   * for some applications since this was libxml1 default behaviour.
   */
  int xmlKeepBlanksDefaultValue = 1;
+ static int xmlKeepBlanksDefaultValueThrDef = 1;
  /**
   * xmlSubstituteEntitiesDefaultValue:
   *
***************
*** 233,241 ****
--- 258,269 ----
   * engine does not handle entities references transparently.
   */
  int xmlSubstituteEntitiesDefaultValue = 0;
+ static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
  
  xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
+ static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
  xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
+ static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
  
  /*
   * Error handling
***************
*** 252,263 ****
--- 280,293 ----
   * Global setting: function used for generic error callbacks
   */
  xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
+ static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
  /**
   * xmlGenericErrorContext:
   *
   * Global setting passed to generic error callbacks
   */
  void *xmlGenericErrorContext = NULL;
+ static void *xmlGenericErrorContextThrDef = NULL;
  
  /*
   * output defaults
***************
*** 269,274 ****
--- 299,305 ----
   * Enabled by default
   */
  int xmlIndentTreeOutput = 1;
+ static int xmlIndentTreeOutputThrDef = 1;
  
  /**
   * xmlTreeIndentString:
***************
*** 276,281 ****
--- 307,313 ----
   * The string used to do one-level indent. By default is equal to "  " (two spaces)
   */
  const char *xmlTreeIndentString = "  ";
+ static const char *xmlTreeIndentStringThrDef = "  ";
  
  /**
   * xmlSaveNoEmptyTags:
***************
*** 286,291 ****
--- 318,324 ----
   * Disabled by default
   */
  int xmlSaveNoEmptyTags = 0;
+ int xmlSaveNoEmptyTagsThrDef = 0;
  
  /**
   * xmlDefaultSAXHandler:
***************
*** 427,432 ****
--- 460,466 ----
      /*
       * Perform initialization as required by libxml
       */
+     xmlMutexLock(xmlThrDefMutex);
  
  #ifdef LIBXML_DOCB_ENABLED
      initdocbDefaultSAXHandler(&gs->docbDefaultSAXHandler);
***************
*** 434,450 ****
  #ifdef LIBXML_HTML_ENABLED
      inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
  #endif
-     initGenericErrorDefaultFunc(&gs->xmlGenericError);
  
      gs->oldXMLWDcompatibility = 0;
!     gs->xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
!     gs->xmlDefaultBufferSize = BASE_BUFFER_SIZE;
      initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
      gs->xmlDefaultSAXLocator.getPublicId = getPublicId;
      gs->xmlDefaultSAXLocator.getSystemId = getSystemId;
      gs->xmlDefaultSAXLocator.getLineNumber = getLineNumber;
      gs->xmlDefaultSAXLocator.getColumnNumber = getColumnNumber;
!     gs->xmlDoValidityCheckingDefaultValue = 0;
  #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
      gs->xmlFree = (xmlFreeFunc) xmlMemFree;
      gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
--- 468,484 ----
  #ifdef LIBXML_HTML_ENABLED
      inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
  #endif
  
      gs->oldXMLWDcompatibility = 0;
!     gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
!     gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
      initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
      gs->xmlDefaultSAXLocator.getPublicId = getPublicId;
      gs->xmlDefaultSAXLocator.getSystemId = getSystemId;
      gs->xmlDefaultSAXLocator.getLineNumber = getLineNumber;
      gs->xmlDefaultSAXLocator.getColumnNumber = getColumnNumber;
!     gs->xmlDoValidityCheckingDefaultValue = 
!          xmlDoValidityCheckingDefaultValueThrDef;
  #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
      gs->xmlFree = (xmlFreeFunc) xmlMemFree;
      gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
***************
*** 458,478 ****
      gs->xmlRealloc = (xmlReallocFunc) realloc;
      gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup;
  #endif
!     gs->xmlGenericErrorContext = NULL;
!     gs->xmlGetWarningsDefaultValue = 1;
!     gs->xmlIndentTreeOutput = 1;
!     gs->xmlTreeIndentString = "  ";
!     gs->xmlKeepBlanksDefaultValue = 1;
!     gs->xmlLineNumbersDefaultValue = 0;
!     gs->xmlLoadExtDtdDefaultValue = 0;
!     gs->xmlParserDebugEntities = 0;
      gs->xmlParserVersion = LIBXML_VERSION_STRING;
!     gs->xmlPedanticParserDefaultValue = 0;
!     gs->xmlSaveNoEmptyTags = 0;
!     gs->xmlSubstituteEntitiesDefaultValue = 0;
  
!     gs->xmlRegisterNodeDefaultValue = NULL;
!     gs->xmlDeregisterNodeDefaultValue = NULL;
  }
  
  /**
--- 492,527 ----
      gs->xmlRealloc = (xmlReallocFunc) realloc;
      gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup;
  #endif
!     gs->xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
!     gs->xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
!     gs->xmlTreeIndentString = xmlTreeIndentStringThrDef;
!     gs->xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
!     gs->xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
!     gs->xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
!     gs->xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
      gs->xmlParserVersion = LIBXML_VERSION_STRING;
!     gs->xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
!     gs->xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
!     gs->xmlSubstituteEntitiesDefaultValue = 
!         xmlSubstituteEntitiesDefaultValueThrDef;
! 
!     gs->xmlGenericError = xmlGenericErrorThrDef;
!     gs->xmlGenericErrorContext = xmlGenericErrorContextThrDef;
!     gs->xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
!     gs->xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
  
!     xmlMutexUnlock(xmlThrDefMutex);
! }
! 
! void
! xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
!     xmlMutexLock(xmlThrDefMutex);
!     xmlGenericErrorContextThrDef = ctx;
!     if (handler != NULL)
!       xmlGenericErrorThrDef = handler;
!     else
!       xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
!     xmlMutexUnlock(xmlThrDefMutex);
  }
  
  /**
***************
*** 493,498 ****
--- 542,562 ----
      return(old);
  }
  
+ xmlRegisterNodeFunc
+ xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
+ {
+     xmlRegisterNodeFunc old;
+     
+     xmlMutexLock(xmlThrDefMutex);
+     old = xmlRegisterNodeDefaultValueThrDef;
+     
+     __xmlRegisterCallbacks = 1;
+     xmlRegisterNodeDefaultValueThrDef = func;
+     xmlMutexUnlock(xmlThrDefMutex);
+ 
+     return(old);
+ }
+ 
  /**
   * xmlDeregisterNodeDefault:
   * @func: function pointer to the new DeregisterNodeFunc
***************
*** 511,516 ****
--- 575,595 ----
      return(old);
  }
  
+ xmlDeregisterNodeFunc
+ xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+ {
+     xmlDeregisterNodeFunc old;
+ 
+     xmlMutexLock(xmlThrDefMutex);
+     old = xmlDeregisterNodeDefaultValueThrDef;
+     
+     __xmlRegisterCallbacks = 1;
+     xmlDeregisterNodeDefaultValueThrDef = func;
+     xmlMutexUnlock(xmlThrDefMutex);
+ 
+     return(old);
+ }
+ 
  
  #ifdef LIBXML_DOCB_ENABLED
  #undef        docbDefaultSAXHandler
***************
*** 558,563 ****
--- 637,650 ----
      else
        return (&xmlGetGlobalState()->xmlBufferAllocScheme);
  }
+ xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
+     xmlBufferAllocationScheme ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlBufferAllocSchemeThrDef;
+     xmlBufferAllocSchemeThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlDefaultBufferSize
  int *
***************
*** 567,572 ****
--- 654,667 ----
      else
        return (&xmlGetGlobalState()->xmlDefaultBufferSize);
  }
+ int xmlThrDefDefaultBufferSize(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlDefaultBufferSizeThrDef;
+     xmlDefaultBufferSizeThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlDefaultSAXHandler
  xmlSAXHandler *
***************
*** 594,599 ****
--- 689,702 ----
      else
        return (&xmlGetGlobalState()->xmlDoValidityCheckingDefaultValue);
  }
+ int xmlThrDefDoValidityCheckingDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlDoValidityCheckingDefaultValueThrDef;
+     xmlDoValidityCheckingDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlGenericError
  xmlGenericErrorFunc *
***************
*** 621,626 ****
--- 724,737 ----
      else
        return (&xmlGetGlobalState()->xmlGetWarningsDefaultValue);
  }
+ int xmlThrDefGetWarningsDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlGetWarningsDefaultValueThrDef;
+     xmlGetWarningsDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlIndentTreeOutput
  int *
***************
*** 630,635 ****
--- 741,754 ----
      else
        return (&xmlGetGlobalState()->xmlIndentTreeOutput);
  }
+ int xmlThrDefIndentTreeOutput(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlIndentTreeOutputThrDef;
+     xmlIndentTreeOutputThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlTreeIndentString
  const char * *
***************
*** 639,644 ****
--- 758,771 ----
      else
        return (&xmlGetGlobalState()->xmlTreeIndentString);
  }
+ const char * xmlThrDefTreeIndentString(const char * v) {
+     const char * ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlTreeIndentStringThrDef;
+     xmlTreeIndentStringThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlKeepBlanksDefaultValue
  int *
***************
*** 648,653 ****
--- 775,788 ----
      else
        return (&xmlGetGlobalState()->xmlKeepBlanksDefaultValue);
  }
+ int xmlThrDefKeepBlanksDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlKeepBlanksDefaultValueThrDef;
+     xmlKeepBlanksDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlLineNumbersDefaultValue
  int *
***************
*** 657,662 ****
--- 792,805 ----
      else
        return (&xmlGetGlobalState()->xmlLineNumbersDefaultValue);
  }
+ int xmlThrDefLineNumbersDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlLineNumbersDefaultValueThrDef;
+     xmlLineNumbersDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlLoadExtDtdDefaultValue
  int *
***************
*** 666,671 ****
--- 809,822 ----
      else
        return (&xmlGetGlobalState()->xmlLoadExtDtdDefaultValue);
  }
+ int xmlThrDefLoadExtDtdDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlLoadExtDtdDefaultValueThrDef;
+     xmlLoadExtDtdDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlParserDebugEntities
  int *
***************
*** 675,680 ****
--- 826,839 ----
      else
        return (&xmlGetGlobalState()->xmlParserDebugEntities);
  }
+ int xmlThrDefParserDebugEntities(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlParserDebugEntitiesThrDef;
+     xmlParserDebugEntitiesThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlParserVersion
  const char * *
***************
*** 693,698 ****
--- 852,865 ----
      else
        return (&xmlGetGlobalState()->xmlPedanticParserDefaultValue);
  }
+ int xmlThrDefPedanticParserDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlPedanticParserDefaultValueThrDef;
+     xmlPedanticParserDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlSaveNoEmptyTags
  int *
***************
*** 702,707 ****
--- 869,882 ----
      else
        return (&xmlGetGlobalState()->xmlSaveNoEmptyTags);
  }
+ int xmlThrDefSaveNoEmptyTags(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlSaveNoEmptyTagsThrDef;
+     xmlSaveNoEmptyTagsThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlSubstituteEntitiesDefaultValue
  int *
***************
*** 711,716 ****
--- 886,899 ----
      else
        return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue);
  }
+ int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
+     int ret;
+     xmlMutexLock(xmlThrDefMutex);
+     ret = xmlSubstituteEntitiesDefaultValueThrDef;
+     xmlSubstituteEntitiesDefaultValueThrDef = v;
+     xmlMutexUnlock(xmlThrDefMutex);
+     return ret;
+ }
  
  #undef        xmlRegisterNodeDefaultValue
  xmlRegisterNodeFunc *
import string, sys, time
import thread
from threading import Thread, Lock

import libxml2

THREADS_COUNT = 15

failed = 0

class ErrorHandler:

    def __init__(self):
        self.errors = []
        self.lock = Lock()

    def handler(self,ctx,str):
        self.lock.acquire()
        self.errors.append(str)
        self.lock.release()

def getLineNumbersDefault():
    old = libxml2.lineNumbersDefault(0)
    libxml2.lineNumbersDefault(old)
    return old

def test(expectedLineNumbersDefault):
    time.sleep(1)
    global failed
    # check a per thread-global
    if expectedLineNumbersDefault != getLineNumbersDefault():
        failed = 1
        print "FAILED to obtain correct value for " \
              "lineNumbersDefault in thread %d" % thread.get_ident()
    # check ther global error handler 
    # (which is NOT per-thread in the python bindings)
    try:
        doc = libxml2.parseFile("bad.xml")
    except:
        pass
    else:
        assert "failed"

# global error handler
eh = ErrorHandler()
libxml2.registerErrorHandler(eh.handler,"")

# set on the main thread only
libxml2.lineNumbersDefault(1) 
test(1)
ec = len(eh.errors)
if ec == 0:
    print "FAILED: should have obtained errors"
    sys.exit(1)

ts = []
for i in range(THREADS_COUNT):
    # expect 0 for lineNumbersDefault because
    # the new value has been set on the main thread only
    ts.append(Thread(target=test,args=(0,)))
for t in ts:
    t.start()
for t in ts:
    t.join()

if len(eh.errors) != ec+THREADS_COUNT*ec:
    print "FAILED: did not obtain the correct number of errors"
    sys.exit(1)

# set lineNumbersDefault for future new threads
libxml2.thrDefLineNumbersDefaultValue(1)
ts = []
for i in range(THREADS_COUNT):
    # expect 1 for lineNumbersDefault
    ts.append(Thread(target=test,args=(1,)))
for t in ts:
    t.start()
for t in ts:
    t.join()

if len(eh.errors) != ec+THREADS_COUNT*ec*2:
    print "FAILED: did not obtain the correct number of errors"
    sys.exit(1)

if failed:
    print "FAILED"
    sys.exit(1)

# Memory debug specific
libxml2.cleanupParser()
if libxml2.debugMemory(1) == 0:
    print "OK"
else:
    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
    libxml2.dumpMemory()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]