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
# # ******************************************************************* # * 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
#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; };
/* ******************************************************************* * * * 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
/* **************************************************** * 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; };
/* **************************************************** * 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
#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; };
/* ******************************************************************* * * * 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
/* **************************************************** * 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; }
Posix Thread Test By Arash Partow - 2003 1.) How to make: make ThreadTest 2.) How to run: ./ThreadTest.exe
-- 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/