You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by db...@apache.org on 2001/02/02 23:24:48 UTC
cvs commit: xml-xalan/c/Tests/Threads ThreadTest.cpp ThreadTest.dsp
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"