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"