From 208b983734d7431699f4bd3534e08321e42ada86 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 6 Oct 2011 03:25:22 +0000 Subject: Renamed most of the core threading system, some ancillary systems need some kind of prefix or something, we could stick with Ito, I will until I think of something else. --- src/condition.cpp | 49 +++++++++++++++++++++++ src/condition.h | 90 +++++++++++++++++++++++++++++++++++++++++++ src/ito.cpp | 55 -------------------------- src/ito.h | 107 --------------------------------------------------- src/itocondition.cpp | 49 ----------------------- src/itocondition.h | 90 ------------------------------------------- src/itocounter.h | 4 +- src/itolocker.cpp | 13 ------- src/itolocker.h | 18 --------- src/itomutex.cpp | 34 ---------------- src/itomutex.h | 68 -------------------------------- src/itoqueue.h | 8 ++-- src/itoserver.h | 12 +++--- src/mutex.cpp | 34 ++++++++++++++++ src/mutex.h | 68 ++++++++++++++++++++++++++++++++ src/mutexlocker.cpp | 24 ++++++++++++ src/mutexlocker.h | 21 ++++++++++ src/thread.cpp | 55 ++++++++++++++++++++++++++ src/thread.h | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ 19 files changed, 460 insertions(+), 446 deletions(-) create mode 100644 src/condition.cpp create mode 100644 src/condition.h delete mode 100644 src/ito.cpp delete mode 100644 src/ito.h delete mode 100644 src/itocondition.cpp delete mode 100644 src/itocondition.h delete mode 100644 src/itolocker.cpp delete mode 100644 src/itolocker.h delete mode 100644 src/itomutex.cpp delete mode 100644 src/itomutex.h create mode 100644 src/mutex.cpp create mode 100644 src/mutex.h create mode 100644 src/mutexlocker.cpp create mode 100644 src/mutexlocker.h create mode 100644 src/thread.cpp create mode 100644 src/thread.h diff --git a/src/condition.cpp b/src/condition.cpp new file mode 100644 index 0000000..2f55ce2 --- /dev/null +++ b/src/condition.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include + +#include "bu/condition.h" + +Bu::Condition::Condition() +{ + pthread_cond_init( &cond, NULL ); +} + +Bu::Condition::~Condition() +{ + pthread_cond_destroy( &cond ); +} + +int Bu::Condition::wait() +{ + return pthread_cond_wait( &cond, &mutex ); +} + +int Bu::Condition::wait( int nSec, int nUSec ) +{ + struct timeval now; + struct timespec timeout; + struct timezone tz; + + gettimeofday( &now, &tz ); + timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); + timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; + + return pthread_cond_timedwait( &cond, &mutex, &timeout ); +} + +int Bu::Condition::signal() +{ + return pthread_cond_signal( &cond ); +} + +int Bu::Condition::broadcast() +{ + return pthread_cond_broadcast( &cond ); +} + diff --git a/src/condition.h b/src/condition.h new file mode 100644 index 0000000..71634f5 --- /dev/null +++ b/src/condition.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_CONDITION_H +#define BU_CONDITION_H + +#include + +#include "bu/mutex.h" + +namespace Bu +{ + /** + * Ito condition. This is a fairly simple condition mechanism. As you may + * notice this class inherits from the Mutex class, this is because all + * conditions must be within a locked block. The standard usage of a + * condition is to pause one thread, perhaps indefinately, until another + * thread signals that it is alright to procede. + *
+ * Standard usage for the thread that wants to wait is as follows: + *
+	 * Condition cond;
+	 * ... // Perform setup and enter your run loop
+	 * cond.lock();
+	 * while( !isFinished() ) // Could be anything you're waiting for
+	 *     cond.wait();
+	 * ...  // Take care of what you have to.
+	 * cond.unlock();
+	 * 
+ * The usage for the triggering thread is much simpler, when it needs to + * tell the others that it's time to grab some data it calls either signal + * or broadcast. See both of those functions for the difference. + *@ingroup Threading + */ + class Condition : public Mutex + { + public: + /** + * Create a condition. + */ + Condition(); + + /** + * Destroy a condition. + */ + ~Condition(); + + /** + * Wait forever, or until signalled. This has to be called from within + * a locked section, i.e. before calling this this object's lock + * function should be called. + */ + int wait(); + + /** + * Wait for a maximum of nSec seconds and nUSec micro-seconds or until + * signalled. This is a little more friendly function if you want to + * perform other operations in the thrad loop that calls this function. + * Like the other wait function, this must be inside a locked section. + *@param nSec The seconds to wait. + *@param nUSec the micro-seconds to wait. + */ + int wait( int nSec, int nUSec ); + + /** + * Notify the next thread waiting on this condition that they can go + * ahead. This only signals one thread, the next one in the condition + * queue, that it is safe to procede with whatever operation was being + * waited on. + */ + int signal(); + + /** + * Notify all threads waiting on this condition that they can go ahead + * now. This function is slower than signal, but more effective in + * certain situations where you may not know how many threads should be + * activated. + */ + int broadcast(); + + private: + pthread_cond_t cond; /**< Internal condition reference. */ + }; +} + +#endif diff --git a/src/ito.cpp b/src/ito.cpp deleted file mode 100644 index aa9a597..0000000 --- a/src/ito.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2007-2011 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#include "bu/ito.h" - -#include "bu/config.h" - -Bu::Ito::Ito() -{ -} - -Bu::Ito::~Ito() -{ -} - -bool Bu::Ito::start() -{ - nHandle = pthread_create( &ptHandle, NULL, threadRunner, this ); - - return true; -} - -bool Bu::Ito::stop() -{ - pthread_cancel( ptHandle ); - - return true; -} - -void *Bu::Ito::threadRunner( void *pThread ) -{ - ((Ito *)pThread)->run(); - pthread_exit( NULL ); - return NULL; -} - -bool Bu::Ito::join() -{ - pthread_join( ptHandle, NULL ); - return true; -} - -void Bu::Ito::yield() -{ -#ifndef WIN32 - pthread_yield(); -#else - #warning Bu::Ito::yield IS A STUB for WIN32!!!! -#endif -} - diff --git a/src/ito.h b/src/ito.h deleted file mode 100644 index 9f50b2a..0000000 --- a/src/ito.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2007-2011 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#ifndef BU_ITO_H -#define BU_ITO_H - -#include - -namespace Bu -{ - /** - * Simple thread class. This wraps the basic pthread (posix threads) - * system in an object oriented sort of way. It allows you to create a - * class with standard member variables and callable functions that can be - * run in it's own thread, one per class instance. - *@ingroup Threading - */ - class Ito - { - public: - /** - * Construct an Ito thread. - */ - Ito(); - - /** - * Destroy an Ito thread. - */ - virtual ~Ito(); - - /** - * Begin thread execution. This will call the overridden run function, - * which will simply execute in it's own thread until the function - * exits, the thread is killed, or the thread is cancelled (optionally). - * The thread started in this manner has access to all of it's class - * variables, but be sure to protect possible multiple-access with - * ItoMutex objects. - * @returns True if starting the thread was successful. False if - * something went wrong and the thread has not started. - */ - bool start(); - - /** - * Forcibly kill a thread. This is not generally considered a good - * thing to do, but in those rare cases you need it, it's invaluable. - * The problem with stopping (or killing) a thread is that it stops it - * the moment you call stop, no matter what it's doing. The object - * oriented approach to this will help clean up any class variables - * that were used, but anything not managed as a member variable will - * probably create a memory leak type of situation. Instead of stop, - * consider using cancel, which can be handled by the running thread in - * a graceful manner. - *@returns True if the thread was stopped, false otherwise. When this - * function returns the thread may not have stopped, to ensure that the - * thread has really stopped, call join. - */ - bool stop(); - - /** - * Join the thread in action. This function performs what is commonly - * called a thread join. That is that it effectively makes the calling - * thread an the Ito thread contained in the called object one in the - * same, and pauses the calling thread until the called thread exits. - * That is, when called from, say, your main(), mythread.join() will - * not return until the thread mythread has exited. This is very handy - * at the end of programs to ensure all of your data was cleaned up. - *@returns True if the thread was joined, false if the thread couldn't - * be joined, usually because it isn't running to begin with. - */ - bool join(); - - private: - pthread_t ptHandle; /**< Internal handle to the posix thread. */ - int nHandle; /**< Numeric handle to the posix thread. */ - - protected: - /** - * The workhorse of the Ito class. This is the function that will run - * in the thread, when this function exits the thread dies and is - * cleaned up by the system. Make sure to read up on ItoMutex, - * ItoCondition, and cancel to see how to control and protect - * everything you do in a safe way within this function. - *@returns I'm not sure right now, but this is the posix standard form. - */ - virtual void run()=0; - - /** - * This is the hidden-heard of the thread system. While run is what the - * user gets to override, and everything said about it is true, this is - * the function that actually makes up the thread, it simply calls the - * run member function in an OO-friendly way. This is what allows us to - * use member variables from within the thread itself. - *@param pThread Should always be this. - *@returns This is specified by posix, I'm not sure yet. - */ - static void *threadRunner( void *pThread ); - - void yield(); - - }; -} - -#endif diff --git a/src/itocondition.cpp b/src/itocondition.cpp deleted file mode 100644 index 3d8db60..0000000 --- a/src/itocondition.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2011 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#include - -#include "bu/itocondition.h" - -Bu::ItoCondition::ItoCondition() -{ - pthread_cond_init( &cond, NULL ); -} - -Bu::ItoCondition::~ItoCondition() -{ - pthread_cond_destroy( &cond ); -} - -int Bu::ItoCondition::wait() -{ - return pthread_cond_wait( &cond, &mutex ); -} - -int Bu::ItoCondition::wait( int nSec, int nUSec ) -{ - struct timeval now; - struct timespec timeout; - struct timezone tz; - - gettimeofday( &now, &tz ); - timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); - timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; - - return pthread_cond_timedwait( &cond, &mutex, &timeout ); -} - -int Bu::ItoCondition::signal() -{ - return pthread_cond_signal( &cond ); -} - -int Bu::ItoCondition::broadcast() -{ - return pthread_cond_broadcast( &cond ); -} - diff --git a/src/itocondition.h b/src/itocondition.h deleted file mode 100644 index 88e8d6c..0000000 --- a/src/itocondition.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007-2011 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#ifndef BU_ITO_CONDITION_H -#define BU_ITO_CONDITION_H - -#include - -#include "itomutex.h" - -namespace Bu -{ - /** - * Ito condition. This is a fairly simple condition mechanism. As you may - * notice this class inherits from the ItoMutex class, this is because all - * conditions must be within a locked block. The standard usage of a - * condition is to pause one thread, perhaps indefinately, until another - * thread signals that it is alright to procede. - *
- * Standard usage for the thread that wants to wait is as follows: - *
-	 * ItoCondition cond;
-	 * ... // Perform setup and enter your run loop
-	 * cond.lock();
-	 * while( !isFinished() ) // Could be anything you're waiting for
-	 *     cond.wait();
-	 * ...  // Take care of what you have to.
-	 * cond.unlock();
-	 * 
- * The usage for the triggering thread is much simpler, when it needs to - * tell the others that it's time to grab some data it calls either signal - * or broadcast. See both of those functions for the difference. - *@ingroup Threading - */ - class ItoCondition : public ItoMutex - { - public: - /** - * Create a condition. - */ - ItoCondition(); - - /** - * Destroy a condition. - */ - ~ItoCondition(); - - /** - * Wait forever, or until signalled. This has to be called from within - * a locked section, i.e. before calling this this object's lock - * function should be called. - */ - int wait(); - - /** - * Wait for a maximum of nSec seconds and nUSec micro-seconds or until - * signalled. This is a little more friendly function if you want to - * perform other operations in the thrad loop that calls this function. - * Like the other wait function, this must be inside a locked section. - *@param nSec The seconds to wait. - *@param nUSec the micro-seconds to wait. - */ - int wait( int nSec, int nUSec ); - - /** - * Notify the next thread waiting on this condition that they can go - * ahead. This only signals one thread, the next one in the condition - * queue, that it is safe to procede with whatever operation was being - * waited on. - */ - int signal(); - - /** - * Notify all threads waiting on this condition that they can go ahead - * now. This function is slower than signal, but more effective in - * certain situations where you may not know how many threads should be - * activated. - */ - int broadcast(); - - private: - pthread_cond_t cond; /**< Internal condition reference. */ - }; -} - -#endif diff --git a/src/itocounter.h b/src/itocounter.h index 10df467..10126a5 100644 --- a/src/itocounter.h +++ b/src/itocounter.h @@ -8,7 +8,7 @@ #ifndef BU_ITO_COUNTER_H #define BU_ITO_COUNTER_H -#include "itomutex.h" +#include "mutex.h" namespace Bu { @@ -42,7 +42,7 @@ namespace Bu private: T tCounter; /**< The counter itself. */ - ItoMutex mOperate; /**< The master mutex, used on all operations. */ + Mutex mOperate; /**< The master mutex, used on all operations. */ }; } diff --git a/src/itolocker.cpp b/src/itolocker.cpp deleted file mode 100644 index 17e97fd..0000000 --- a/src/itolocker.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "bu/itolocker.h" -#include "bu/itomutex.h" - -Bu::ItoLocker::ItoLocker( Bu::ItoMutex &mu ) : - mu( mu ) -{ - mu.lock(); -} - -Bu::ItoLocker::~ItoLocker() -{ - mu.unlock(); -} diff --git a/src/itolocker.h b/src/itolocker.h deleted file mode 100644 index 76e5198..0000000 --- a/src/itolocker.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef BU_ITO_LOCKER_H -#define BU_ITO_LOCKER_H - -namespace Bu -{ - class ItoMutex; - class ItoLocker - { - public: - ItoLocker( ItoMutex &mu ); - virtual ~ItoLocker(); - - private: - ItoMutex & mu; - }; -}; - -#endif diff --git a/src/itomutex.cpp b/src/itomutex.cpp deleted file mode 100644 index 8de6336..0000000 --- a/src/itomutex.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007-2011 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#include "bu/itomutex.h" - -Bu::ItoMutex::ItoMutex() -{ - pthread_mutex_init( &mutex, NULL ); -} - -Bu::ItoMutex::~ItoMutex() -{ - pthread_mutex_destroy( &mutex ); -} - -int Bu::ItoMutex::lock() -{ - return pthread_mutex_lock( &mutex ); -} - -int Bu::ItoMutex::unlock() -{ - return pthread_mutex_unlock( &mutex ); -} - -int Bu::ItoMutex::trylock() -{ - return pthread_mutex_trylock( &mutex ); -} - diff --git a/src/itomutex.h b/src/itomutex.h deleted file mode 100644 index 68a0c1d..0000000 --- a/src/itomutex.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007-2011 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#ifndef BU_ITO_MUTEX_H -#define BU_ITO_MUTEX_H - -#include - -namespace Bu -{ - /** - * Simple mutex wrapper. Currently this doesn't do anything extra for you - * except keep all of the functionality together in an OO sorta' way and - * keep you from having to worry about cleaning up your mutexes properly, - * or initing them. - *@ingroup Threading - */ - class ItoMutex - { - public: - /** - * Create an unlocked mutex. - */ - ItoMutex(); - - /** - * Destroy a mutex. This can only be done when a mutex is unlocked. - * Failure to unlock before destroying a mutex object could cause it to - * wait for the mutex to unlock, the odds of which are usually farily - * low at deconstruction time. - */ - ~ItoMutex(); - - /** - * Lock the mutex. This causes all future calls to lock on this - * instance of mutex to block until the first thread that called mutex - * unlocks it. At that point the next thread that called lock will get - * a chance to go to work. Because of the nature of a mutex lock it is - * a very bad idea to do any kind of serious or rather time consuming - * computation within a locked section. This can cause thread-deadlock - * and your program may hang. - */ - int lock(); - - /** - * Unlock the mutex. This allows the next thread that asked for a lock - * to lock the mutex and continue with execution. - */ - int unlock(); - - /** - * Try to lock the mutex. This is the option to go with if you cannot - * avoid putting lengthy operations within a locked section. trylock - * will attempt to lock the mutex, if the mutex is already locked this - * function returns immediately with an error code. - */ - int trylock(); - - protected: - pthread_mutex_t mutex; /**< The internal mutex reference. */ - }; -} - -#endif diff --git a/src/itoqueue.h b/src/itoqueue.h index dc3cadb..039e09c 100644 --- a/src/itoqueue.h +++ b/src/itoqueue.h @@ -10,8 +10,8 @@ #include -#include "itomutex.h" -#include "itocondition.h" +#include "mutex.h" +#include "condition.h" namespace Bu { @@ -232,8 +232,8 @@ namespace Bu Item *pEnd; /**< The end of the queue, the last element to dequeue. */ long nSize; /**< The number of items in the queue. */ - ItoMutex mOperate; /**< The master mutex, used on all operations. */ - ItoCondition cBlock; /**< The condition for blocking dequeues. */ + Mutex mOperate; /**< The master mutex, used on all operations. */ + Condition cBlock; /**< The condition for blocking dequeues. */ }; } diff --git a/src/itoserver.h b/src/itoserver.h index 902c684..75b3349 100644 --- a/src/itoserver.h +++ b/src/itoserver.h @@ -16,8 +16,8 @@ #include "bu/string.h" #include "bu/list.h" -#include "bu/ito.h" -#include "bu/itomutex.h" +#include "bu/thread.h" +#include "bu/mutex.h" #include "bu/itoqueue.h" #include "bu/set.h" @@ -50,7 +50,7 @@ namespace Bu * happening within the server itself, and actually makes it useful. *@ingroup Threading Serving */ - class ItoServer : public Ito + class ItoServer : public Thread { friend class ItoClient; friend class SrvClientLinkFactory; @@ -74,7 +74,7 @@ namespace Bu private: class SrvClientLink; - class ItoClient : public Ito + class ItoClient : public Thread { friend class Bu::ItoServer::SrvClientLink; public: @@ -96,7 +96,7 @@ namespace Bu int iPort; int nTimeoutSec; int nTimeoutUSec; - ItoMutex imProto; + Mutex imProto; }; class SrvClientLink : public Bu::ClientLink @@ -132,7 +132,7 @@ namespace Bu typedef ItoQueue ClientQueue; ClientHash hClients; ClientQueue qClientCleanup; - ItoMutex imClients; + Mutex imClients; void clientCleanup( int iSocket ); }; diff --git a/src/mutex.cpp b/src/mutex.cpp new file mode 100644 index 0000000..dbaaece --- /dev/null +++ b/src/mutex.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/mutex.h" + +Bu::Mutex::Mutex() +{ + pthread_mutex_init( &mutex, NULL ); +} + +Bu::Mutex::~Mutex() +{ + pthread_mutex_destroy( &mutex ); +} + +int Bu::Mutex::lock() +{ + return pthread_mutex_lock( &mutex ); +} + +int Bu::Mutex::unlock() +{ + return pthread_mutex_unlock( &mutex ); +} + +int Bu::Mutex::trylock() +{ + return pthread_mutex_trylock( &mutex ); +} + diff --git a/src/mutex.h b/src/mutex.h new file mode 100644 index 0000000..b5c8b7a --- /dev/null +++ b/src/mutex.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_MUTEX_H +#define BU_MUTEX_H + +#include + +namespace Bu +{ + /** + * Simple mutex wrapper. Currently this doesn't do anything extra for you + * except keep all of the functionality together in an OO sorta' way and + * keep you from having to worry about cleaning up your mutexes properly, + * or initing them. + *@ingroup Threading + */ + class Mutex + { + public: + /** + * Create an unlocked mutex. + */ + Mutex(); + + /** + * Destroy a mutex. This can only be done when a mutex is unlocked. + * Failure to unlock before destroying a mutex object could cause it to + * wait for the mutex to unlock, the odds of which are usually farily + * low at deconstruction time. + */ + ~Mutex(); + + /** + * Lock the mutex. This causes all future calls to lock on this + * instance of mutex to block until the first thread that called mutex + * unlocks it. At that point the next thread that called lock will get + * a chance to go to work. Because of the nature of a mutex lock it is + * a very bad idea to do any kind of serious or rather time consuming + * computation within a locked section. This can cause thread-deadlock + * and your program may hang. + */ + int lock(); + + /** + * Unlock the mutex. This allows the next thread that asked for a lock + * to lock the mutex and continue with execution. + */ + int unlock(); + + /** + * Try to lock the mutex. This is the option to go with if you cannot + * avoid putting lengthy operations within a locked section. trylock + * will attempt to lock the mutex, if the mutex is already locked this + * function returns immediately with an error code. + */ + int trylock(); + + protected: + pthread_mutex_t mutex; /**< The internal mutex reference. */ + }; +} + +#endif diff --git a/src/mutexlocker.cpp b/src/mutexlocker.cpp new file mode 100644 index 0000000..90b730e --- /dev/null +++ b/src/mutexlocker.cpp @@ -0,0 +1,24 @@ +#include "bu/mutexlocker.h" +#include "bu/mutex.h" + +Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : + mu( mu ) +{ + mu.lock(); +} + +Bu::MutexLocker::~MutexLocker() +{ + mu.unlock(); +} + +void Bu::MutexLocker::unlock() +{ + mu.unlock(); +} + +void Bu::MutexLocker::relock() +{ + mu.lock(); +} + diff --git a/src/mutexlocker.h b/src/mutexlocker.h new file mode 100644 index 0000000..7c3c97e --- /dev/null +++ b/src/mutexlocker.h @@ -0,0 +1,21 @@ +#ifndef BU_MUTEX_LOCKER_H +#define BU_MUTEX_LOCKER_H + +namespace Bu +{ + class Mutex; + class MutexLocker + { + public: + MutexLocker( Mutex &mu ); + virtual ~MutexLocker(); + + void unlock(); + void relock(); + + private: + Mutex μ + }; +}; + +#endif diff --git a/src/thread.cpp b/src/thread.cpp new file mode 100644 index 0000000..e4563a2 --- /dev/null +++ b/src/thread.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/thread.h" + +#include "bu/config.h" + +Bu::Thread::Thread() +{ +} + +Bu::Thread::~Thread() +{ +} + +bool Bu::Thread::start() +{ + nHandle = pthread_create( &ptHandle, NULL, threadRunner, this ); + + return true; +} + +bool Bu::Thread::stop() +{ + pthread_cancel( ptHandle ); + + return true; +} + +void *Bu::Thread::threadRunner( void *pThread ) +{ + ((Thread *)pThread)->run(); + pthread_exit( NULL ); + return NULL; +} + +bool Bu::Thread::join() +{ + pthread_join( ptHandle, NULL ); + return true; +} + +void Bu::Thread::yield() +{ +#ifndef WIN32 + pthread_yield(); +#else + #warning Bu::Thread::yield IS A STUB for WIN32!!!! +#endif +} + diff --git a/src/thread.h b/src/thread.h new file mode 100644 index 0000000..70e6f5f --- /dev/null +++ b/src/thread.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_THREAD_H +#define BU_THREAD_H + +#include + +namespace Bu +{ + /** + * Simple thread class. This wraps the basic pthread (posix threads) + * system in an object oriented sort of way. It allows you to create a + * class with standard member variables and callable functions that can be + * run in it's own thread, one per class instance. + *@ingroup Threading + */ + class Thread + { + public: + /** + * Construct an Thread thread. + */ + Thread(); + + /** + * Destroy an Thread thread. + */ + virtual ~Thread(); + + /** + * Begin thread execution. This will call the overridden run function, + * which will simply execute in it's own thread until the function + * exits, the thread is killed, or the thread is cancelled (optionally). + * The thread started in this manner has access to all of it's class + * variables, but be sure to protect possible multiple-access with + * ThreadMutex objects. + * @returns True if starting the thread was successful. False if + * something went wrong and the thread has not started. + */ + bool start(); + + /** + * Forcibly kill a thread. This is not generally considered a good + * thing to do, but in those rare cases you need it, it's invaluable. + * The problem with stopping (or killing) a thread is that it stops it + * the moment you call stop, no matter what it's doing. The object + * oriented approach to this will help clean up any class variables + * that were used, but anything not managed as a member variable will + * probably create a memory leak type of situation. Instead of stop, + * consider using cancel, which can be handled by the running thread in + * a graceful manner. + *@returns True if the thread was stopped, false otherwise. When this + * function returns the thread may not have stopped, to ensure that the + * thread has really stopped, call join. + */ + bool stop(); + + /** + * Join the thread in action. This function performs what is commonly + * called a thread join. That is that it effectively makes the calling + * thread an the Thread thread contained in the called object one in the + * same, and pauses the calling thread until the called thread exits. + * That is, when called from, say, your main(), mythread.join() will + * not return until the thread mythread has exited. This is very handy + * at the end of programs to ensure all of your data was cleaned up. + *@returns True if the thread was joined, false if the thread couldn't + * be joined, usually because it isn't running to begin with. + */ + bool join(); + + private: + pthread_t ptHandle; /**< Internal handle to the posix thread. */ + int nHandle; /**< Numeric handle to the posix thread. */ + + protected: + /** + * The workhorse of the Thread class. This is the function that will run + * in the thread, when this function exits the thread dies and is + * cleaned up by the system. Make sure to read up on ThreadMutex, + * ThreadCondition, and cancel to see how to control and protect + * everything you do in a safe way within this function. + *@returns I'm not sure right now, but this is the posix standard form. + */ + virtual void run()=0; + + /** + * This is the hidden-heard of the thread system. While run is what the + * user gets to override, and everything said about it is true, this is + * the function that actually makes up the thread, it simply calls the + * run member function in an OO-friendly way. This is what allows us to + * use member variables from within the thread itself. + *@param pThread Should always be this. + *@returns This is specified by posix, I'm not sure yet. + */ + static void *threadRunner( void *pThread ); + + void yield(); + + }; +} + +#endif -- cgit v1.2.3