Update of /cvsroot/sharedaemon/sharedaemon-ui-web/src/thread In directory sc8-pr-cvs1:/tmp/cvs-serv659/src/thread Modified Files: Mutex.cpp Condition.cpp Condition.h Added Files: Thread.cpp Semaphore.cpp Thread.h Semaphore.h Log Message: 24/12/2003 Barbeaux * Added simple test programs for Exceptions and Threads. * Implemented Semaphore and Thread. --- NEW FILE: Thread.cpp --- /* * This file is part of webInterface. * Copyright (C) 2003 Mikael Barbeaux <mik...@us...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Thread.h" /** * Creates a thread object. * Initializes parameters only. */ Thread::Thread() : Condition(), thread(0), cancel_th(false), running(false) {} /** * Thread destructor * Waits for the thread to terminate before deleting it. */ Thread::~Thread() throw (ThreadException) { lock(); if(thread) { // try to cancel thread execution if still running cancel_th = true; if(running) waitForSignal(); // wait for thread to terminate #ifdef _WIN32_ ::WaitForSingleObject(*thread, INFINITE); #else ::pthread_join(*thread, 0); #endif // delete thread delete thread; } unlock(); } /** * Launch the thread */ void *Thread::launch(void* th) throw (ThreadException) { // Retrieve the thread to launch Thread *thread = (Thread*) th; // signal waiting threads that it is going to be run thread->lock(); thread->running = true; thread->sendSignal(); thread->unlock(); // run thread->run(); // signal waiting threads that it is terminated thread->lock(); thread->running = false; thread->sendBroadcastSignal(); thread->unlock(); return 0; } /** * Sets a cancellation point. */ void Thread::setCancelPoint() throw (ThreadException) { lock(); // exit thread if cancellation has been requested if(cancel_th) { running = false; sendBroadcastSignal(); unlock(); #ifdef _WIN32_ ::ExitThread(0); #else ::pthread_exit(0); #endif } unlock(); } /** * Cancels the thread execution. */ void Thread::cancel() { cancel_th = true; } /** * Tests if the thread is currently running. */ bool Thread::isRunning() { return running; } /** * Make the current thread stop execution * for the given time. */ void Thread::sleep(float time) throw (ThreadException) { if(time < 0) throw ThreadException(ThreadExcp, "Invalid sleep time.", "Thread::sleep"); // sleep #ifdef _WIN32_ ::Sleep((unsigned int) (1000*time)); #else if(::usleep((unsigned int) (1000000*time)) != 0) throw ThreadException(ThreadExcp, "Cannot sleep", "Thread::sleep"); #endif } /** * Starts the thread execution. */ void Thread::start() throw (ThreadException) { lock(); // Allocates pthread thread = new pthread_t; if(thread == 0) throw ThreadException(ThreadExcp, "Cannot allocate the thread.", "Thread::start"); #ifdef _WIN32_ if((*thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) launch, this, 0 ,0)) == 0) throw ThreadException(ThreadExcp, "Cannot create the thread.", "Thread::start"); #else if(::pthread_create(thread, 0, launch, this) != 0) throw ThreadException(ThreadExcp, "Cannot create the thread.", "Thread::start"); #endif // wait for thread to start if(! running) waitForSignal(); unlock(); } /** * Wait for the condition, with locks * if given parameter is true. */ void Thread::wait(bool toLock) throw (ThreadException) { if(toLock) lock(); if(running) waitForSignal(); if(toLock) unlock(); } --- NEW FILE: Semaphore.cpp --- /* * This file is part of webInterface. * Copyright (C) 2003 Mikael Barbeaux <mik...@us...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Semaphore.h" /** * Posts a signal. */ void Semaphore::post() throw (ThreadException) { lock(); ++number; if(number <= 0) sendSignal(); unlock(); } /** * Tries to enter the semaphore without any wait. */ bool Semaphore::tryWait() throw (ThreadException) { lock(); if(number <= 0) { unlock(); return false; } --number; if(number < 0) waitForSignal(); unlock(); return true; } /** * Wait for the semaphore to let the thread enter. */ void Semaphore::wait() throw (ThreadException) { lock(); --number; if(number < 0) waitForSignal(); unlock(); } --- NEW FILE: Thread.h --- /* * This file is part of webInterface. * Copyright (C) 2003 Mikael Barbeaux <mik...@us...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _THREAD_H_ #define _THREAD_H_ #include "Condition.h" #ifdef _WIN32_ #include <windows.h> /** * As pthread doesn't exist for Windows, * create the object type. */ typedef HANDLE pthread_t; #else #include <pthread.h> #include <unistd.h> #include <sys/errno.h> #endif /** * Defines a Thread object. * A thread is used to run a part of code into a * system condition-thread. Implements the run() * method to define what your thread must do. */ class Thread : public Condition { private: /** * Launch the thread */ static void *launch(void* th) throw (ThreadException); protected: // the thread pthread_t *thread; // cancel ? bool cancel_th; // running ? bool running; /** * Defines what the thread will do. */ virtual void run() = 0; /** * Sets a cancellation point. */ void setCancelPoint() throw (ThreadException); public: /** * Creates a thread object. */ Thread(); /** * Thread destructor. */ virtual ~Thread() throw (ThreadException); /** * Cancels the thread execution. */ void cancel(); /** * Tests if the thread is currently running. * * @return bool */ bool isRunning(); /** * Make the current thread stop execution * for the given time. * * @param time */ static void sleep(float time) throw (ThreadException); /** * Starts the thread execution. */ void start() throw (ThreadException); /** * Wait for the condition, with locks * if given parameter is true. * * @param bool */ void wait(bool toLock = true) throw (ThreadException); }; #endif --- NEW FILE: Semaphore.h --- /* * This file is part of webInterface. * Copyright (C) 2003 Mikael Barbeaux <mik...@us...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SEMAPHORE_H_ #define _SEMAPHORE_H_ #include "Condition.h" #include "../exceptions/ThreadException.h" /** * Defines a Semaphore object. * A semaphore is a condition with a maximum * number of executing thread. If this number * is reached, every threads that will try * to enter the semaphore will be waiting for * another thread to leave the semaphore. */ class Semaphore : public Condition { protected: // Max number of executing threads. int number; public: /** * Creates a semaphore with the given maximum * number of executings threads. * * @param nb */ Semaphore(unsigned int nb) throw (ThreadException) : number(nb) {} /** * Semaphore destructor */ ~Semaphore() {} /** * Returns the max number of executings threads. * * @return unsigned int */ unsigned int getNumber() { return number; } /** * Posts a signal. */ void post() throw (ThreadException); /** * Sets the maximum number of executing threads. */ void setNumber(unsigned int nb) { number = nb; } /** * Tries to enter the semaphore without any wait. * * @return bool */ bool tryWait() throw (ThreadException); /** * Wait for the semaphore to let the thread enter. */ void wait() throw (ThreadException); }; #endif Index: Mutex.cpp =================================================================== RCS file: /cvsroot/sharedaemon/sharedaemon-ui-web/src/thread/Mutex.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Mutex.cpp 24 Dec 2003 11:52:49 -0000 1.1 +++ Mutex.cpp 24 Dec 2003 13:03:54 -0000 1.2 @@ -28,16 +28,16 @@ // Allocate mutex mutex = new pthread_mutex_t; if(mutex == 0) - throw ThreadException(MutexError, "Cannot allocate the mutex.", + throw ThreadException(MutexExcp, "Cannot allocate the mutex.", "Mutex::Mutex"); // Initialize the mutex #ifdef _WIN32_ if((*mutex = ::CreateMutex(0,0,0)) == 0) - throw ThreadException(MutexError, "Cannot create the mutex", + throw ThreadException(MutexExcp, "Cannot create the mutex", "Mutex::Mutex"); #else if(::pthread_mutex_init(mutex, 0)) - throw ThreadException(MutexError, "Cannot create the mutex", + throw ThreadException(MutexExcp, "Cannot create the mutex", "Mutex::Mutex"); #endif } @@ -73,11 +73,11 @@ #ifdef _WIN32_ // waits indefinitively for the mutex... if(::WaitForSingleObject(*mutex, INFINITE) != WAIT_OBJECT_0) - throw ThreadException(MutexError, "Cannot lock the mutex.", + throw ThreadException(MutexExcp, "Cannot lock the mutex.", "Mutex::lock"); #else if(::pthread_mutex_lock(mutex) != 0) - throw ThreadException(MutexError, "Cannot lock the mutex.", + throw ThreadException(MutexExcp, "Cannot lock the mutex.", "Mutex::lock"); #endif } @@ -98,7 +98,7 @@ if(ret == WAIT_TIMEOUT) return false; else if(ret != WAIT_OBJECT_0) - throw ThreadException(MutexError, "Cannot tryLock the mutex.", + throw ThreadException(MutexExcp, "Cannot tryLock the mutex.", "Mutex::tryLock"); return true; #else @@ -106,7 +106,7 @@ if(ret == EBUSY) return false; else if(ret != 0) - throw ThreadException(MutexError, "Cannot tryLock the mutex", + throw ThreadException(MutexExcp, "Cannot tryLock the mutex", "Mutex::tryLock"); return true; #endif @@ -119,11 +119,11 @@ // Unlocking the mutex... #ifdef _WIN32_ if(::ReleaseMutex(*mutex) == 0) - throw ThreadException(MutexError, "Cannot unlock the mutex.", + throw ThreadException(MutexExcp, "Cannot unlock the mutex.", "Mutex::unlock"); #else if(::pthread_mutex_unlock(mutex) != 0) - throw ThreadException(MutexError, "Cannot unlock the mutex.", + throw ThreadException(MutexExcp, "Cannot unlock the mutex.", "Mutex::unlock"); #endif } Index: Condition.cpp =================================================================== RCS file: /cvsroot/sharedaemon/sharedaemon-ui-web/src/thread/Condition.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Condition.cpp 24 Dec 2003 11:52:49 -0000 1.1 +++ Condition.cpp 24 Dec 2003 13:03:54 -0000 1.2 @@ -26,7 +26,7 @@ Condition::Condition() throw (ThreadException){ condition = new pthread_cond_t; if(condition == 0) - throw ThreadException(ConditionError, "Cannot allocate the condition.", + throw ThreadException(ConditionExcp, "Cannot allocate the condition.", "Condition::Condition"); #ifdef _WIN32_ // Init struct parameters @@ -40,12 +40,12 @@ can't create condition. */ if((condition->semaphore == 0) || (condition->waiters_done == 0)) - throw ThreadException(ConditionError, "Cannot create the condition.", + throw ThreadException(ConditionExcp, "Cannot create the condition.", "Condition::Condition"); #else // init pthread condition if(::pthread_cond_init(condition, 0) != 0) - throw ThreadException(ConditionError, "Cannot create the condition.", + throw ThreadException(ConditionExcp, "Cannot create the condition.", "Condition::Condition"); #endif } @@ -92,7 +92,7 @@ INFINITE, false) != WAIT_OBJECT_0) { // semaphore is invalid unlock(); - throw ThreadException(ConditionError, "Invalid semaphore.", + throw ThreadException(ConditionExcp, "Invalid semaphore.", "Condition::waitforSignal"); } // Waiting time is finished, we leave the waiting area @@ -108,7 +108,7 @@ INFINITE, false) != WAIT_OBJECT_0) { // the mutex is invalid unlock(); - throw ThreadException(ConditionError, "Invalid mutex.", + throw ThreadException(ConditionExcp, "Invalid mutex.", "Condition::waitForSignal"); } } @@ -117,13 +117,13 @@ else if(::WaitForSingleObject(*mutex_t, INFINITE) != WAIT_OBJECT_0) { unlock(); - throw ThreadException(ConditionError, "Invalid mutex.", + throw ThreadException(ConditionExcp, "Invalid mutex.", "Condition::waitForSignal"); } #else if(::pthread_cond_wait(condition, mutex) != 0) { unlock(); - throw ThreadException(ConditionError, "Invalid condition.", + throw ThreadException(ConditionExcp, "Invalid condition.", "Condition::waitForSignal"); } #endif @@ -144,13 +144,13 @@ (::ReleaseSemaphore(condition->semaphore,1,0) == 0)) { // if the condition is invalid unlock(); - throw ThreadException(ConditionError, "Invalid condition.", + throw ThreadException(ConditionExcp, "Invalid condition.", "Condition::sendSignal"); } #else if(::pthread_cond_signal(condition) != 0) { unlock(); - throw ThreadException(ConditionError, "Invalid condition", + throw ThreadException(ConditionExcp, "Invalid condition", "Condition::sendSignal"); } #endif @@ -171,7 +171,7 @@ condition->nb_waiting, 0)) { // Can't release the semaphore unlock(); - throw ThreadException(ConditionError, "Cannot release the semaphore.", + throw ThreadException(ConditionExcp, "Cannot release the semaphore.", "Condition::sendBroadcastSignal"); } LeaveCriticalSection(&(condition->waiting_lock)); @@ -179,7 +179,7 @@ if(::WaitForSingleObject(condition->waiters_done, INFINITE) != WAIT_OBJECT_0) { unlock(); - throw ThreadException(ConditionError, "Invalid event.", + throw ThreadException(ConditionExcp, "Invalid event.", "Condition::sendBroadcastSignal"); } condition->broadcast = false; @@ -188,7 +188,7 @@ #else if(::pthread_cond_broadcast(condition) != 0) { unlock(); - throw ThreadException(ConditionError, "Invalid condition.", + throw ThreadException(ConditionExcp, "Invalid condition.", "Condition::sendBroadcastSignal"); } #endif Index: Condition.h =================================================================== RCS file: /cvsroot/sharedaemon/sharedaemon-ui-web/src/thread/Condition.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Condition.h 24 Dec 2003 11:52:49 -0000 1.1 +++ Condition.h 24 Dec 2003 13:03:54 -0000 1.2 @@ -17,8 +17,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _CONDITION_H -#define _CONDITION_H +#ifndef _CONDITION_H_ +#define _CONDITION_H_ #include "Mutex.h" #include "../exceptions/ThreadException.h" |