blob: e4ad5a3080f3e30cf14be76fddee56f89b495543 [file] [log] [blame]
// Base header file. Must be first.
#include <Include/PlatformDefinitions.hpp>
#include <cassert>
#include <ctime>
#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#else
#include <iostream>
#endif
#include <util/PlatformUtils.hpp>
#include <util/Mutexes.hpp>
#include <Include/XalanAutoPtr.hpp>
#include <XalanTransformer/XalanTransformer.hpp>
#if defined(WIN32)
//This is here for the threads.
#include <process.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(XALAN_POSIX2_AVAILABLE)
#include <pthread.h>
#include <unistd.h>
#else
#error Unsupported platform!
#endif
#if !defined(XALAN_NO_NAMESPACES)
using std::cerr;
using std::cout;
using std::endl;
#endif
// This is here for memory leak testing.
#if defined(_DEBUG)
#include <crtdbg.h>
#endif
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
{
return m_counter;
}
struct
ThreadInfo
{
ThreadInfo(
unsigned int theThreadNumber = 0,
SynchronizedCounter* theCounter = 0) :
m_threadNumber(theThreadNumber),
m_counter(theCounter)
{
}
unsigned int m_threadNumber;
SynchronizedCounter* m_counter;
};
// Used to hold compiled stylesheet and pre-parsed source...
const XalanCompiledStylesheet* glbCompiledStylesheet = 0;
const XalanParsedSource* glbParsedSource = 0;
#if defined(WIN32)
extern "C" void theThreadRoutine(void* param);
void
#elif defined(XALAN_POSIX2_AVAILABLE)
extern "C" void* theThreadRoutine(void* param);
void*
#else
#error Unsupported platform!
#endif
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.
#if defined(XALAN_OLD_STYLE_CASTS)
const ThreadInfo* const theInfo = (const ThreadInfo*)param;
#else
const ThreadInfo* const theInfo = reinterpret_cast<const ThreadInfo*>(param);
#endif
assert(theInfo != 0);
theInfo->m_counter->increment();
try
{
// Our input file. The assumption is that the executable will be run
// from same directory as the input files.
// Generate the output file name.
const XalanDOMString theOutputFile(
XalanDOMString("birds") +
UnsignedLongToDOMString(theInfo->m_threadNumber) +
XalanDOMString(".out"));
// Create a transformer...
XalanTransformer theTransformer;
// Do the transform...
theTransformer.transform(*glbParsedSource, glbCompiledStylesheet, XSLTResultTarget(theOutputFile));
}
catch(...)
{
cerr << "Exception caught in thread " << theInfo->m_threadNumber;
}
// Decrement the counter because we're done...
theInfo->m_counter->decrement();
#if defined(XALAN_POSIX2_AVAILABLE)
return 0;
#endif
}
inline void
doSleep(unsigned int theMilliseconds)
{
#if defined(WIN32)
Sleep(theMilliseconds);
#elif defined(XALAN_POSIX2_AVAILABLE)
usleep(theMilliseconds * 10);
#else
#error Unsupported platform!
#endif
}
void
doThreads(long theThreadCount)
{
cout << endl << "Starting " << theThreadCount << " threads." << endl;
XalanArrayAutoPtr<ThreadInfo> theThreadInfo(new ThreadInfo[theThreadCount]);
try
{
cout << endl << "Clock before starting threads: " << clock() << endl;
SynchronizedCounter theCounter;
long i = 0;
while (i < theThreadCount)
{
theThreadInfo[i].m_threadNumber = i;
theThreadInfo[i].m_counter = &theCounter;
#if defined(WIN32)
const unsigned long theThreadID =
_beginthread(theThreadRoutine, 4096, reinterpret_cast<LPVOID>(&theThreadInfo[i]));
if (theThreadID == unsigned(-1))
{
cerr << endl << "Unable to create thread number " << i + 1 << "." << endl;
}
#elif defined(XALAN_POSIX2_AVAILABLE)
pthread_t theThread;
const int theResult = pthread_create(&theThread, 0, theThreadRoutine, (void*)&theThreadInfo[i]);
if (theResult != 0)
{
cerr << endl << "Unable to create thread number " << i + 1 << "." << endl;
}
else
{
#if defined(OS390)
pthread_detach(&theThread);
#else
pthread_detach(theThread);
#endif
}
#else
#error Unsupported platform!
#endif
++i;
}
clock_t theClock = 0;
if (i == 0)
{
cerr << endl << "No threads were created!" << endl;
}
else
{
unsigned int theCheckCount = 0;
do
{
doSleep(2000);
// Check a couple of times, just in case, since
// getCounter() is not synchronized...
if (theCounter.getCounter() == 0)
{
if (theCheckCount == 0)
{
theClock = clock();
}
++theCheckCount;
}
}
while(theCheckCount < 2);
}
cout << endl << "Clock after threads: " << theClock << endl;
}
catch(...)
{
cerr << "Exception caught!!!"
<< endl
<< endl;
}
}
int
main(
int argc,
const char* argv[])
{
#if !defined(NDEBUG) && defined(_MSC_VER)
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif
if (argc > 2)
{
cerr << "Usage: ThreadTest"
<< endl
<< endl;
}
else
{
int threadCount = 60;
if (argc == 2)
{
threadCount = atoi(argv[1]);
}
try
{
// Initialize Xerces...
XMLPlatformUtils::Initialize();
// Initialize Xalan...
XalanTransformer::initialize();
{
// Create a XalanTransformer. We won't actually use this to transform --
// it's just acting likely a factory for the compiled stylesheet and
// pre-parsed source.
XalanTransformer theXalanTransformer;
const char* const theXSLFileName = "birds.xsl";
theXalanTransformer.compileStylesheet(theXSLFileName, glbCompiledStylesheet);
assert(glbCompiledStylesheet != 0);
// Compile the XML source document as well. All threads will use
// this binary representation of the source tree.
const char* const theXMLFileName = "birds.xml";
theXalanTransformer.parseSource(theXMLFileName, glbParsedSource);
assert(glbParsedSource != 0);
doThreads(threadCount);
}
// Terminate Xalan...
XalanTransformer::terminate();
// Terminate Xerces...
XMLPlatformUtils::Terminate();
}
catch(...)
{
cerr << "Exception caught!!!"
<< endl
<< endl;
}
}
return 0;
}