dbertoni    01/02/02 14:24:47

  Modified:    c/Tests/Threads ThreadTest.cpp ThreadTest.dsp
  Log:
  Fixed up problems with using lots of threads.
  
  Revision  Changes    Path
  1.5       +199 -74   xml-xalan/c/Tests/Threads/ThreadTest.cpp
  
  Index: ThreadTest.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/Tests/Threads/ThreadTest.cpp,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ThreadTest.cpp    2001/02/02 17:10:49     1.4
  +++ ThreadTest.cpp    2001/02/02 22:24:40     1.5
  @@ -1,9 +1,13 @@
   #include <cassert>
  +#include <climits>
   #include <fstream>
   #include <iostream>
   #include <strstream>
   
  +#include <process.h>
  +
   #include <util/PlatformUtils.hpp>
  +#include <util/Mutexes.hpp>
   
   #include <PlatformSupport/DOMStringHelper.hpp>
   #include <PlatformSupport/XalanFileOutputStream.hpp>
  @@ -29,7 +33,7 @@
   #define WIN32_LEAN_AND_MEAN
   #include <windows.h>
   #include <winbase.h>
  -#define THREADFUNCTIONRETURN DWORD WINAPI
  +
   
   #if !defined(XALAN_NO_NAMESPACES)
        using std::cerr;
  @@ -49,106 +53,227 @@
   // Used to hold compiled stylesheet
   StylesheetRoot* glbStylesheetRoot;
   
  +extern "C" void theThreadRoutine(void* param);
  +
  +
  +class SynchronizedCounter
  +{
  +public:
  +
  +     SynchronizedCounter();
  +
  +     ~SynchronizedCounter();
  +
  +     void
  +     increment();
  +
  +     void
  +     decrement();
  +
  +     unsigned long
  +     getCounter() const;
  +
  +private:
  +
  +     mutable XMLMutex        m_mutex;
  +
  +     unsigned long           m_counter;
  +};
  +
  +
  +
  +SynchronizedCounter::SynchronizedCounter() :
  +     m_mutex(),
  +     m_counter(0)
  +{
  +}
  +
  +
  +
  +SynchronizedCounter::~SynchronizedCounter()
  +{
  +}
  +
  +
  +
  +void
  +SynchronizedCounter::increment()
  +{
  +     XMLMutexLock    theLock(&m_mutex);
  +
  +     if (m_counter < ULONG_MAX)
  +     {
  +             ++m_counter;
  +     }
  +}
  +
  +
  +
  +void
  +SynchronizedCounter::decrement()
  +{
  +     XMLMutexLock    theLock(&m_mutex);
  +
  +     if (m_counter > 0)
  +     {
  +             --m_counter;
  +     }
  +}
  +
  +
  +
  +unsigned long
  +SynchronizedCounter::getCounter() const
  +{
  +     XMLMutexLock    theLock(&m_mutex);
  +
  +     return m_counter;
  +}
  +
  +
  +
  +struct
  +ThreadInfo
  +{
  +     ThreadInfo(
  +                     unsigned int                    theThreadNumber,
  +                     SynchronizedCounter*    theCounter) :
  +             m_threadNumber(theThreadNumber),
  +             m_counter(theCounter)
  +     {
  +     }
  +
  +     unsigned int                    m_threadNumber;
  +
  +     SynchronizedCounter*    m_counter;
  +};
  +
   
  -THREADFUNCTIONRETURN theThread(LPVOID        param)
  +
  +void
  +theThreadRoutine(void*               param)
   {
   // This routine uses compiled stylesheet (glbStylesheetRoot), which is set 
using the 
   // theProcessor.setStylesheetRoot method. The transform is done using the 
theProcessor's
   // process() method.
  +
  +     const ThreadInfo*       theInfo = reinterpret_cast<const 
ThreadInfo*>(param);
  +
  +     assert(theInfo != 0);
   
  -     const int       number = reinterpret_cast<int>(param);
  -     const DWORD             theThreadID = GetCurrentThreadId();
  +     theInfo->m_counter->increment();
   
  -     // Create the support objects that are necessary for running the 
processor...
  -     XalanSourceTreeDOMSupport               theDOMSupport;
  -     XalanSourceTreeParserLiaison    theParserLiaison(theDOMSupport);
  -
  -     theDOMSupport.setParserLiaison(&theParserLiaison);
  -     // The default is that documents are not thread-safe.  Set this to
  -     // true so they are.
  -     //theParserLiaison.setThreadSafe(true);
  -
  -     XSLTProcessorEnvSupportDefault  theXSLTProcessorEnvSupport;
  -     XObjectFactoryDefault                   theXObjectFactory;
  -     XPathFactoryDefault                             theXPathFactory;
  -
  -     // Create a processor...and output start message.
  -     XSLTEngineImpl  theProcessor(
  -                                     theParserLiaison,
  -                                     theXSLTProcessorEnvSupport,
  -                                     theDOMSupport,
  -                                     theXObjectFactory,
  -                                     theXPathFactory);
  -
  -     // Connect the processor to the support object...
  -     theXSLTProcessorEnvSupport.setProcessor(&theProcessor);
  -
  -     // The execution context uses the same factory support objects as
  -     // the processor, since those objects have the same lifetime as
  -     // other objects created as a result of the execution.
  -     StylesheetExecutionContextDefault       ssExecutionContext(
  -                                             theProcessor,
  +     try
  +     {
  +             // Create the support objects that are necessary for running 
the processor...
  +             XalanSourceTreeDOMSupport               theDOMSupport;
  +             XalanSourceTreeParserLiaison    theParserLiaison(theDOMSupport);
  +
  +             theDOMSupport.setParserLiaison(&theParserLiaison);
  +             // The default is that documents are not thread-safe.  Set this 
to
  +             // true so they are.
  +             //theParserLiaison.setThreadSafe(true);
  +
  +             XSLTProcessorEnvSupportDefault  theXSLTProcessorEnvSupport;
  +             XObjectFactoryDefault                   theXObjectFactory;
  +             XPathFactoryDefault                             theXPathFactory;
  +
  +             // Create a processor...and output start message.
  +             XSLTEngineImpl  theProcessor(
  +                                             theParserLiaison,
                                                theXSLTProcessorEnvSupport,
                                                theDOMSupport,
  -                                             theXObjectFactory);
  +                                             theXObjectFactory,
  +                                             theXPathFactory);
   
  -     // Our input files.  The assumption is that the executable will be run
  -     // from same directory as the input files.
  +             // Connect the processor to the support object...
  +             theXSLTProcessorEnvSupport.setProcessor(&theProcessor);
   
  -     // Generate the input and output file names.
  -     char buffer[10];
  -     const XalanDOMString theXMLfile("birds.xml");
  -     const XalanDOMString outPutfile(XalanDOMString("birds") + 
XalanDOMString(itoa(number,buffer,10)) + XalanDOMString(".out"));
  +             // The execution context uses the same factory support objects 
as
  +             // the processor, since those objects have the same lifetime as
  +             // other objects created as a result of the execution.
  +             StylesheetExecutionContextDefault       ssExecutionContext(
  +                                                     theProcessor,
  +                                                     
theXSLTProcessorEnvSupport,
  +                                                     theDOMSupport,
  +                                                     theXObjectFactory);
  +
  +             // Our input files.  The assumption is that the executable will 
be run
  +             // from same directory as the input files.
  +
  +             // Generate the input and output file names.
  +             const XalanDOMString    theXMLfile("birds.xml");
  +
  +             const XalanDOMString    theOutputFile(
  +                             XalanDOMString("birds") +
  +                             
UnsignedLongToDOMString(theInfo->m_threadNumber) +
  +                             XalanDOMString(".out"));
  +
  +             //Generate the XML input and output objects.
  +             XSLTInputSource         theInputSource(c_wstr(theXMLfile));
  +             XSLTResultTarget        theResultTarget(theOutputFile);
  +
  +             // Set the stylesheet to be the compiled stylesheet. Then do 
the transform. 
  +             // Report both the start of the transform and end of the thread.
  +             theProcessor.setStylesheetRoot(glbStylesheetRoot);
  +             
theProcessor.process(theInputSource,theResultTarget,ssExecutionContext);
  +     }
  +     catch(...)
  +     {
  +     }
   
  +     // Decrement the counter because we're done...
  +     theInfo->m_counter->decrement();
  +}
   
  -     //Generate the XML input and output objects.
  -     XSLTInputSource         theInputSource(c_wstr(theXMLfile));
  -     XSLTResultTarget        theResultTarget(outPutfile);
   
  -     // Set the stylesheet to be the compiled stylesheet. Then do the 
transform. 
  -     // Report both the start of the transform and end of the thread.
  -     theProcessor.setStylesheetRoot(glbStylesheetRoot);
  -     theProcessor.process(theInputSource,theResultTarget,ssExecutionContext);
   
  -     return (0);
  -}
  -void doThreads(int x)
  +void
  +doThreads(long       theThreadCount)
   {
  -     cout << endl << "Starting " << x << " threads." << endl;
  +     cout << endl << "Starting " << theThreadCount << " threads." << endl;
  +
  +     typedef std::vector<ThreadInfo>         ThreadInfoVectorType;
   
  -     DWORD dwStackSize = 4096;               // initial thread stack size
  -     LPTHREAD_START_ROUTINE lpStartAddress = 
(LPTHREAD_START_ROUTINE)theThread;
  -     DWORD dwCreationFlags = 0;              // creation flags
  -     int nThreads = x;
  +     ThreadInfoVectorType    theThreadInfo;
   
  -     std::vector<HANDLE> hThreads;
  -     hThreads.reserve(nThreads);
  -     int i=0;
  -     
  +     theThreadInfo.reserve(theThreadCount);
  +
        try
        {
                cout << endl << "Clock before starting threads: " << clock() << 
endl;
  +
  +             SynchronizedCounter             theCounter;
  +
  +             for (long i = 0; i < theThreadCount; i++)
  +             {
  +                     
theThreadInfo.push_back(ThreadInfoVectorType::value_type(i, &theCounter));
  +
  +                     const unsigned long             theThreadID =
  +                                     _beginthread(theThreadRoutine, 4096, 
reinterpret_cast<LPVOID>(&theThreadInfo.back()));
   
  -             for (i=0; i< nThreads; i++)
  +                     if (theThreadID == unsigned(-1))
                        {
  -                             HANDLE hThread;
  -                             DWORD  threadID;
  +                             cerr << endl << "Unable to create thread number 
" << i + 1 << "." << endl;
  +                     }
  +             }
   
  -                             hThread = CreateThread(
  -                                     0, dwStackSize,
  -                                     lpStartAddress,                         
        // pointer to thread function
  -                                     reinterpret_cast<LPVOID>(i),    // 
argument for new thread
  -                                     dwCreationFlags,                        
        // creation flags
  -                                     &threadID);
  -                             assert(hThread != 0);
  -                             hThreads.push_back(hThread);
  +             if (theThreadInfo.size() == 0)
  +             {
  +                     cerr << endl << "No threads were created!" << endl;
  +             }
  +             else
  +             {
  +                     do
  +                     {
  +                             Sleep(2000);
                        }
  -             WaitForMultipleObjects(hThreads.size(), &hThreads[0], TRUE, 
INFINITE);
  +                     while(theCounter.getCounter() != 0);
   
  -             cout << endl << "Clock after threads: " << clock() << endl;
  +                     Sleep(2000);
  +             }
   
  -             for (i=0; i< nThreads; i++)
  -                     CloseHandle(hThreads[i]);
  +             cout << endl << "Clock after threads: " << clock() << endl;
        }
        catch(...)
        {
  
  
  
  1.2       +28 -1     xml-xalan/c/Tests/Threads/ThreadTest.dsp
  
  Index: ThreadTest.dsp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/Tests/Threads/ThreadTest.dsp,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ThreadTest.dsp    2000/10/11 17:27:35     1.1
  +++ ThreadTest.dsp    2001/02/02 22:24:43     1.2
  @@ -19,6 +19,7 @@
   !MESSAGE 
   !MESSAGE "ThreadTest - Win32 Release" (based on "Win32 (x86) Console 
Application")
   !MESSAGE "ThreadTest - Win32 Debug" (based on "Win32 (x86) Console 
Application")
  +!MESSAGE "ThreadTest - Win32 Release with symbols" (based on "Win32 (x86) 
Console Application")
   !MESSAGE 
   
   # Begin Project
  @@ -42,7 +43,7 @@
   # PROP Ignore_Export_Lib 0
   # PROP Target_Dir ""
   # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D 
"_MBCS" /YX /FD /c
  -# ADD CPP /nologo /MD /W4 /GR /GX /O2 /I "..\..\..\..\xml-xerces\c\src" /I 
"..\..\src\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
  +# ADD CPP /nologo /MD /W4 /GR /GX /O2 /Ob2 /I "..\..\..\..\xml-xerces\c\src" 
/I "..\..\src\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
   # ADD BASE RSC /l 0x409 /d "NDEBUG"
   # ADD RSC /l 0x409 /d "NDEBUG"
   BSC32=bscmake.exe
  @@ -78,12 +79,38 @@
   # ADD LINK32 ..\..\..\..\xml-xerces\c\Build\Win32\VC6\Debug\xerces-c_1D.lib 
..\..\Build\Win32\VC6\Debug\*.lib kernel32.lib user32.lib gdi32.lib 
winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug 
/machine:I386 /pdbtype:sept
   # SUBTRACT LINK32 /pdb:none
   
  +!ELSEIF  "$(CFG)" == "ThreadTest - Win32 Release with symbols"
  +
  +# PROP BASE Use_MFC 0
  +# PROP BASE Use_Debug_Libraries 0
  +# PROP BASE Output_Dir "ThreadTest___Win32_Release_with_symbols"
  +# PROP BASE Intermediate_Dir "ThreadTest___Win32_Release_with_symbols"
  +# PROP BASE Ignore_Export_Lib 0
  +# PROP BASE Target_Dir ""
  +# PROP Use_MFC 0
  +# PROP Use_Debug_Libraries 0
  +# PROP Output_Dir "..\..\Build\Win32\VC6\Release.symbols"
  +# PROP Intermediate_Dir "..\..\Build\Win32\VC6\Release.symbols\ThreadTest"
  +# PROP Ignore_Export_Lib 0
  +# PROP Target_Dir ""
  +# ADD BASE CPP /nologo /MD /W4 /GR /GX /O2 /I "..\..\..\..\xml-xerces\c\src" 
/I "..\..\src\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
  +# ADD CPP /nologo /MD /W4 /GR /GX /Zi /O2 /I "..\..\..\..\xml-xerces\c\src" 
/I "..\..\src\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
  +# ADD BASE RSC /l 0x409 /d "NDEBUG"
  +# ADD RSC /l 0x409 /d "NDEBUG"
  +BSC32=bscmake.exe
  +# ADD BASE BSC32 /nologo
  +# ADD BSC32 /nologo
  +LINK32=link.exe
  +# ADD BASE LINK32 
..\..\..\..\xml-xerces\c\Build\Win32\VC6\Release\xerces-c_1.lib 
..\..\Build\Win32\VC6\Release\*.lib kernel32.lib user32.lib gdi32.lib 
winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib 
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib 
odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 
/out:"..\..\..\c\Build\Win32\VC6\Release/ThreadTest.exe"
  +# ADD LINK32 ..\..\..\..\xml-xerces\c\Build\Win32\VC6\Release\xerces-c_1.lib 
..\..\Build\Win32\VC6\Release.symbols\*.lib kernel32.lib user32.lib gdi32.lib 
winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib 
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib 
odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 
/out:"..\..\..\c\Build\Win32\VC6\Release.symbols/ThreadTest.exe"
  +
   !ENDIF 
   
   # Begin Target
   
   # Name "ThreadTest - Win32 Release"
   # Name "ThreadTest - Win32 Debug"
  +# Name "ThreadTest - Win32 Release with symbols"
   # Begin Group "Source Files"
   
   # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  
  
  

Reply via email to