Mail Archives: cygwin/2003/12/08/23:19:57
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Tue, Dec 09, 2003 at 03:01:56AM +0000, Arash Partow wrote:
>Hello Sherly,
>
>I haven't tried the ThreadTest on a solaris system however ive e-mailed
>someone that does have access to one, they will try it i'll get the results
>back to you, but out of interest what do you think the solaris system will
>do? and how do you think that behaviour will relate to cygiwn?
I must admit that I'm mystified as to what this test is trying to accomplish
but I've modified it so that it will terminate more quickly when a
signal is delivered, rather than continuing to create threads after
CTRL-C is pressed and added some more debugging output.
I've attached the modified source to this message. I also modified the
Makefile so that it created ThreadTest.exe by default.
cgf
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=Makefile
#
# *******************************************************************
# * Makefile *
# * Posix Thread Test Prototype *
# * *
# * Author: Arash Partow *
# * *
# *******************************************************************
#
MAKE = make
CXX = i686-pc-cygwin-g++
OPTIMIZATION_OPT = -O2
OPTIONS = -pedantic -ansi -Wall -g $(OPTIMIZATION_OPT) -o
OPTIONS_LIBS = -pedantic -ansi -Wall -g $(OPTIMIZATION_OPT) -c
#LIBS = -lpthread
#LIBS = -mthreads
LIBS =
OBJS = Thread.o \
Mutex.o \
StringTokenizer.o
ThreadTest.exe: ThreadTestPrototype.o $(OBJS)
$(CXX) $(OPTIONS) $@ $^ $(LIBS)
.cpp.o:
$(CXX) $(OPTIONS_LIBS) $?
clean:
rm -f core *.o *.bak *stackdump *.dll
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Mutex.cpp"
#include "Mutex.h"
Mutex::Mutex() throw(Mutex::Exception)
{
int result;
mutex = PTHREAD_MUTEX_INITIALIZER;
if ((result = pthread_mutex_init(&mutex, NULL)) != 0)
{
throw Exception();
}
};
Mutex::~Mutex()
{
pthread_mutex_destroy(&mutex);
};
void Mutex::lock(void) throw(Mutex::Exception)
{
int result;
tid = pthread_self();
if ((result = pthread_mutex_lock(&mutex)) != 0)
{
/*
ret could be EDEADLK
throw Exception(something about dead lock etc...);
*/
throw Exception();
}
};
void Mutex::unlock(void) throw(Mutex::Exception)
{
int result;
tid = pthread_self();
if ((result = pthread_mutex_unlock(&mutex)) != 0)
{
throw Exception();
}
};
void Mutex::tryLock() throw(Mutex::Exception)
{
#ifndef _LINUX_
if (pthread_mutex_trylock(&mutex) != 0)
{
throw Exception();
}
#endif
};
pthread_t Mutex::getCurrent(void) const
{
return tid;
};
pthread_mutex_t& Mutex::getMutex()
{
return mutex;
};
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Mutex.h"
/*
*******************************************************************
* *
* Class Name: Thread *
* Author: Arash Partow *
* *
*******************************************************************
*/
#ifndef INCLUDE_MUTEX_H
#define INCLUDE_MUTEX_H
#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "StringTokenizer.h"
#include <pthread.h>
#include <sys/types.h>
class Mutex
{
public:
class Exception : public std::exception
{
};
Mutex(void) throw(Exception);
~Mutex(void);
void lock(void) throw(Exception);
void unlock(void) throw(Exception);
void tryLock(void) throw(Exception);
pthread_t getCurrent(void) const;
pthread_mutex_t& getMutex();
private:
pthread_mutex_t mutex;
pthread_t tid;
};
#endif
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="StringTokenizer.cpp"
/*
****************************************************
* Class: StringTokenizer *
* By Arash Partow - 2002 *
* Copyright Arash Partow 2002-2003 *
* All Right Reserved *
****************************************************
*/
#include "StringTokenizer.h"
StringTokenizer::StringTokenizer()
{
tokenStr = "";
delim = "";
};
StringTokenizer::StringTokenizer(string str, string delim)
{
tokenStr = str;
this->delim = delim;
/*
Remove sequential delimiter
*/
unsigned int currentPos = 0;
while(1==1)
{
if ((currentPos = tokenStr.find(delim,currentPos)) != string::npos)
{
currentPos +=delim.length();
while(tokenStr.find(delim,currentPos) == currentPos)
{
tokenStr.erase(currentPos,delim.length());
}
}
else
break;
}
/*
Trim leading delimiter
*/
if (tokenStr.find(delim,0) == 0)
{
tokenStr.erase(0,delim.length());
}
/*
Trim ending delimiter
*/
if (tokenStr.rfind(delim) == (tokenStr.length()-delim.length()))
{
tokenStr.erase(tokenStr.length()-delim.length(),delim.length());
}
};
StringTokenizer::~StringTokenizer()
{
tokenStr = "";
delim = "";
};
int StringTokenizer::countTokens()
{
unsigned int prevPos = 0;
int numTokens = 0;
if (tokenStr.length() > 0)
{
numTokens = 0;
unsigned int currentPos = 0;
while(1==1)
{
if ((currentPos = tokenStr.find(delim,currentPos)) != string::npos)
{
numTokens++;
prevPos = currentPos;
currentPos += delim.length();
}
else
break;
}
return ++numTokens;
}
else
{
return 0;
}
};
bool StringTokenizer::hasMoreTokens()
{
return (tokenStr.length() > 0);
};
string StringTokenizer::nextToken()
{
if (tokenStr.length() == 0) return "";
string tStr ="";
unsigned int pos = tokenStr.find(delim,0);
if (pos != string::npos)
{
tStr = tokenStr.substr(0,pos);
tokenStr = tokenStr.substr(pos+delim.length(),tokenStr.length()-pos);
}
else
{
tStr = tokenStr.substr(0,tokenStr.length());
tokenStr = "";
}
return tStr;
};
int StringTokenizer::nextIntToken()
{
return atoi(nextToken().c_str());
};
double StringTokenizer::nextFloatToken()
{
return atof(nextToken().c_str());
};
string StringTokenizer::nextToken(string delimiter)
{
if (tokenStr.length() == 0) return "";
string tStr ="";
unsigned int pos = tokenStr.find(delimiter,0);
if (pos != string::npos)
{
tStr = tokenStr.substr(0,pos);
tokenStr = tokenStr.substr(pos+delimiter.length(),tokenStr.length()-pos);
}
else
{
tStr = tokenStr.substr(0,tokenStr.length());
tokenStr = "";
}
return tStr;
};
string StringTokenizer::remainingString()
{
return tokenStr;
};
string StringTokenizer::filterNextToken(string filterStr)
{
string str = nextToken();
unsigned int currentPos = 0;
while((currentPos = str.find(filterStr,currentPos)) != string::npos)
{
str.erase(currentPos,filterStr.length());
}
return str;
};
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="StringTokenizer.h"
/*
****************************************************
* Class: StringTokenizer *
* By Arash Partow - 2002 *
* Copyright Arash Partow 2002-2003 *
* All Right Reserved *
****************************************************
*/
#ifndef INCLUDE_STRINGTOKENIZER_H
#define INCLUDE_STRINGTOKENIZER_H
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
class StringTokenizer
{
public:
StringTokenizer();
StringTokenizer(string str, string delim);
~StringTokenizer();
int countTokens();
bool hasMoreTokens();
string nextToken();
int nextIntToken();
double nextFloatToken();
string nextToken(string delim);
string remainingString();
string filterNextToken(string filterStr);
private:
string tokenStr;
string delim;
};
#endif
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Thread.cpp"
#include "Thread.h"
Thread::Thread()
{
currentState = THREAD_IDLE;
};
Thread::~Thread()
{
};
bool Thread::operator==(const Thread& obj) const
{
return (pthread_equal(threadID, obj.threadID) != 0);
};
void Thread::run()
{
setThreadState(THREAD_RUNNING);
execute();
setThreadState(THREAD_DEAD);
};
int Thread::start()
{
int result = 0;
result = pthread_create(&threadID,NULL,&(Thread::threadFunction),this);
if (result)
{
setThreadState(THREAD_DEAD);
cout << "-ERROR- CREATE FAILED ThreadID:" << threadID << " Result: " << result << endl;
cout.flush();
}
else
{
pthread_detach(threadID);
}
return result;
};
void* Thread::threadFunction(void* pt)
{
Thread* thrd = reinterpret_cast<Thread*>(pt);
thrd->run();
return NULL;
};
int Thread::self() const
{
return (int)threadID;
}
void Thread::detach(void) const
{
pthread_detach(threadID);
};
int Thread::join(void)
{
int status = 0;
pthread_join(threadID, (void**)&status);
return status;
};
void Thread::terminate()
{
pthread_cancel(threadID);
};
void Thread::exit()
{
pthread_exit((void**)0);
};
bool Thread::setThreadState(int state)
{
currentState = state;
return true;
};
int Thread::getThreadState()
{
return currentState;
};
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Thread.h"
/*
*******************************************************************
* *
* Class Name: Thread *
* Author: Arash Partow *
* *
*******************************************************************
*/
#ifndef INCLUDE_POSIXTHREAD_H
#define INCLUDE_POSIXTHREAD_H
#define THREAD_IDLE 0
#define THREAD_RUNNING 1
#define THREAD_DEAD 2
#define THREAD_GCR 3
#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "StringTokenizer.h"
#include <pthread.h>
#include <sys/types.h>
class Thread
{
public:
Thread();
virtual ~Thread();
bool operator == (const Thread& obj) const;
int start();
bool setThreadState(int state);
int getThreadState();
void terminate();
void exit();
protected:
virtual void execute()=0;
static void* threadFunction(void *);
void run();
void detach(void) const;
void yield(void) const;
int self() const;
int join(void);
private:
pthread_attr_t attr;
pthread_t threadID;
int currentState;
};
#endif
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ThreadTestPrototype.cpp"
/*
****************************************************
* Thread-Test Prototype *
* By Arash Partow *
* Copyright Arash Partow 2002-2003 *
* All Right Reserved *
****************************************************
*/
#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <windows.h>
#include "StringTokenizer.h"
#include "Thread.h"
#include "Mutex.h"
const int MAX_THREADS = 700;
unsigned int MAX_THREAD_CREATE = 999999999;
Mutex* printlnMutex = NULL;
void sigproc(int sig);
string formatUInt(int val, unsigned int len);
bool println(string str);
class TestThread: public Thread
{
public:
TestThread(int _id):Thread()
{
id = _id;
};
~TestThread()
{
};
string reverseString(string str)
{
char tempch;
/* Reverse the string */
for(unsigned int i=0; i < (str.length()/2); i++)
{
tempch = str[i];
str[i] = str[str.length()-i-1];
str[str.length()-i-1] = tempch;
}
return str;
};
string palindrome(string str)
{
string tempStr = str;
char tempch;
/* Reverse the string */
for(unsigned int i=0; i < (str.length()/2); i++)
{
tempch = str[i];
str[i] = str[str.length()-i-1];
str[str.length()-i-1] = tempch;
}
/* Produce palindrome */
str = tempStr + str;
return str;
};
void execute()
{
string data = "aaaa:bbbb:ccc:dddd:eee:";
/* Build a really large string */
for (int i=0; i < 100; i++) data += "aaaa:bbbb:ccc:dddd:eee:";
StringTokenizer strtok = StringTokenizer(data,":");
/* Get each token in the string */
while (strtok.hasMoreTokens())
{
string token = strtok.nextToken();
token = reverseString(token);
token = palindrome(token);
}
println("Thread ["+formatUInt(id,7)+"] Completed.");
};
private:
int id;
};
typedef vector <TestThread*> ThreadList;
ThreadList threadList;
class GarbageCollector: public Thread
{
public:
GarbageCollector()
{
keepRunning = true;
cleanupComplete = false;
};
~GarbageCollector()
{
};
void terminate()
{
keepRunning = false;
};
bool terminateState()
{
return (!keepRunning);
};
bool isCleanupComplete()
{
return cleanupComplete;
};
void execute()
{
unsigned int count = MAX_THREADS;
while(keepRunning && (count <= MAX_THREAD_CREATE))
{
vector <int> delPos;
/* Find all the current dead threads */
for(unsigned int i=0; i < threadList.size(); i++)
{
if (threadList[i]->getThreadState() == THREAD_DEAD) delPos.push_back(i);
}
/* Recalibrate deletion positions */
for (unsigned int i=1; i < delPos.size(); i++)
{
delPos[i]-=i;
}
for (unsigned int i=0; keepRunning && i < delPos.size(); i++)
{
count++;
/* Erase thread and free-up memory */
if(threadList[delPos[i]] != NULL) delete threadList[delPos[i]];
threadList.erase(threadList.begin()+delPos[i]);
/* Create a new thread to take up the just earsed thread */
TestThread* tempThread = new TestThread(count);
if (tempThread != NULL)
{
/* Add new thread to list and print out info about current thread count */
int result = tempThread->start();
if (result)
{
delete tempThread;
}
else
{
//cout << "Created new thread! [" << formatUInt(count,9) << "] Result: " << result << endl;
println("Created new thread! ("+formatUInt(keepRunning,1)+") [" + formatUInt(count,9) + "] Result: "+ formatUInt(result,1));
threadList.push_back(tempThread);
}
}
}
delPos.clear();
}
cout << "*********************************** thread loop terminated, keepRunning = " << keepRunning << "\n";
cout.flush ();
/* clean up any remaining threads */
while(threadList.size() > 0)
{
vector <int> delPos;
for(unsigned int i=0; i < threadList.size(); i++)
{
if (threadList[i]->getThreadState() == THREAD_DEAD) delPos.push_back(i);
}
/* Recalibrate deletion positions */
for (unsigned int i=1; i < delPos.size(); i++)
{
delPos[i]-=i;
}
for (unsigned int i=0; i < delPos.size(); i++)
{
/* Erase thread and free-up memory */
delete threadList[delPos[i]];
threadList.erase(threadList.begin()+delPos[i]);
}
delPos.clear();
}
if (threadList.size() == 0) cleanupComplete = true;
}
bool keepRunning;
private:
bool cleanupComplete;
};
GarbageCollector* gc;
int main(int argc, char *argv[])
{
signal(SIGINT, sigproc);
printf ("PID %u\n", GetCurrentProcessId ());
sleep (10);
/* Create Println mutex */
printlnMutex = new Mutex();
/* Setup the garbage thread collector */
gc = new GarbageCollector();
if (argc == 2)
{
MAX_THREAD_CREATE = atoi(argv[1]);
cout << "Maximum threads to be created: " << MAX_THREAD_CREATE << endl;
}
cout <<"Creating threads" << endl;
sleep (2);
/*
create the initial MAX_THREAD threads and add
them to the thread list
*/
for(int i=0; gc->keepRunning && i < MAX_THREADS; i++)
{
TestThread* tempThread = new TestThread(i);
threadList.push_back(tempThread);
}
cout <<"Starting threads" << endl;
sleep (2);
/*
Have all the newly created threads start.
*/
for(unsigned int i=0; gc->keepRunning && i < threadList.size(); i++)
{
threadList[i]->start();
println("Created new thread! [" + formatUInt(i,9) + "]~");
}
cout << "Initialize garbage collector" << endl;
cout.flush ();
sleep (5);
/* Initialise garbage collector */
gc->start();
/*
put main thread to sleep
*/
while(!gc->isCleanupComplete()) sleep(1);
cout << endl << "Thread-Test has been completed." << endl;
cout << "Have a nice day...." << endl;
exit(EXIT_SUCCESS);
return 1;
}
void sigproc(int sig)
{
signal(SIGINT, sigproc);
if (gc != NULL)
{
/* Don't call terminate if already in terminate state */
if (gc->terminateState()) return;
cout << endl << endl << endl << endl << endl << ">>>>>>>>>>>>>>>> Processing shutdown procedure..." << endl << endl << endl << endl << endl;
cout.flush();
gc->terminate();
cout << ">>>>>>>>>>>>>>>> Done." << endl;
}
}
string formatUInt(int val, unsigned int len)
{
string tempStr = "";
char buf[100];
sprintf(buf,"%d",val);
tempStr = buf;
while(tempStr.length() < len)
{
tempStr = "0" + tempStr;
}
return tempStr;
}
bool println(string str)
{
printlnMutex->lock();
cout << str << endl;
cout.flush();
printlnMutex->unlock();
return true;
}
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="readme.txt"
Posix Thread Test
By Arash Partow - 2003
1.) How to make:
make ThreadTest
2.) How to run:
./ThreadTest.exe
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
--M9NhX3UHpAaciwkO--
- Raw text -