diff options
Diffstat (limited to 'mcop/thread.h')
-rw-r--r-- | mcop/thread.h | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/mcop/thread.h b/mcop/thread.h new file mode 100644 index 0000000..882e596 --- /dev/null +++ b/mcop/thread.h @@ -0,0 +1,375 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_MCOP_THREAD_H +#define ARTS_MCOP_THREAD_H + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): SystemThreads, Thread, Mutex, ThreadCondition, + * Semaphore + * + * These classes are kept binary compatible. As the threading implementation + * can be changed, also + * + * Thread_impl, Mutex_impl, ThreadCondition_impl and Semaphore_impl need + * to remain as they are. The implementation of these depends on what thread + * system is used, and can attach the required data as necessary to the + * base classes. So i.e. a posix mutex can contain the pthread_mutex_t in + * the PosixMutex_impl. + */ + +namespace Arts { + +class Mutex_impl; +class Thread_impl; +class ThreadCondition_impl; +class Thread; +class Semaphore_impl; + +/** + * Encapsulates the operating system threading facilities + */ +class ARTS_EXPORT SystemThreads { +public: + static SystemThreads *the(); + static bool init(SystemThreads *the); + + /** + * Check whether there is threading support available + * + * If there is no real threading support, the Threading classes try to + * gracefully degrade the performance. For instance, locking a mutex will + * do * nothing, and calling the start() function of a Thread will execute + * it's run function. + * + * @returns true if there are real threads + */ + static bool supported(); + + /** + * Check wether the current thread is the main thread + * + * The main thread is the thread that the application's main() was + * executed in. The IOManager event loop will only run in the main + * thread. + */ + virtual bool isMainThread() = 0; + + virtual Mutex_impl *createMutex_impl() = 0; + virtual Mutex_impl *createRecMutex_impl() = 0; + virtual Thread_impl *createThread_impl(Thread *thread) = 0; + virtual ThreadCondition_impl *createThreadCondition_impl() = 0; + virtual Semaphore_impl *createSemaphore_impl(int, int) = 0; + virtual ~SystemThreads(); + + /** + * Returns a pointer to the current thread, or a null pointer if + * we're the main thread (isMainThread() is true). + */ + virtual Thread *getCurrentThread() = 0; +}; + +/** + * Base class for platform specific thread code + */ +class ARTS_EXPORT Thread_impl +{ +public: + virtual void setPriority(int) =0; + virtual void start() = 0; + virtual void waitDone() = 0; + virtual ~Thread_impl(); +}; + +/** + * Base class for platform specific mutex code + */ +class ARTS_EXPORT Mutex_impl { +public: + virtual void lock() = 0; + virtual bool tryLock() = 0; + virtual void unlock() = 0; + virtual ~Mutex_impl(); +}; + +/** + * Base class for platform specific thread condition code + */ +class ARTS_EXPORT ThreadCondition_impl { +public: + virtual void wakeOne() = 0; + virtual void wakeAll() = 0; + virtual void wait(Mutex_impl *impl) = 0; + virtual ~ThreadCondition_impl(); +}; + +class ARTS_EXPORT Semaphore_impl { +public: + virtual void wait() = 0; + virtual int tryWait() = 0; + virtual void post() = 0; + virtual int getValue() = 0; + virtual ~Semaphore_impl(); +}; + +/** + * A thread of execution + * + * Example for implementing a thread: + * + * <pre> + * class Counter : public Arts::Thread + * { + * public: + * void run() { + * for(int i = 0;i < 10;i++) + * { + * printf("%d\n",i+1); + * sleep(1); + * } + * } + * }; // start the thread with Counter c; c.start(); + * </pre> + */ +class ARTS_EXPORT Thread { +private: + Thread_impl *impl; + +public: + Thread() : impl(SystemThreads::the()->createThread_impl(this)) + { + } + + virtual ~Thread(); + + /** + * set the priority parameters for the thread + * + * FIXME: what should be minimum, maximum, recommended? + */ + inline void setPriority(int priority) { + impl->setPriority(priority); + } + + /** + * starts the run() method in a thread + */ + inline void start() + { + impl->start(); + } + + /** + * waits until the thread is executed completely + */ + inline void waitDone() + { + impl->waitDone(); + } + + /** + * implement this method, if you want to create an own thread - then + * you can simply call thread.start() to start execution of run() in + * a seperate thread + */ + virtual void run() = 0; +}; + +/** + * A mutex + * + * To protect a critical section, you can use a mutex, which will ensure that + * only one thread at a time can lock it. Here is an example for a thread-safe + * random number generator: + * + * <pre> + * class RandomGenerator { + * Arts::Mutex mutex; + * long seed; + * public: + * long get() { + * mutex.lock(); + * // do complicated calculation with seed here + * mutex.unlock(); + * return seed; + * } + * }; + * </pre> + */ +class ARTS_EXPORT Mutex { +private: + Mutex_impl *impl; + friend class ThreadCondition; + +public: + /** + * constructor + * + * @param recursive whether to create a recursive mutex (may be locked by + * the same thread more than once), or a normal mutex + */ + inline Mutex(bool recursive = false) + : impl(recursive?SystemThreads::the()->createRecMutex_impl() + :SystemThreads::the()->createMutex_impl()) + { + } + + /** + * destructor + */ + virtual ~Mutex(); + + /** + * locks the mutex + */ + inline void lock() { + impl->lock(); + } + + /** + * tries to lock the mutex, returning immediately in any case (even if + * mutex is locked by another thread) + * + * @returns true if successful (mutex locked), false otherwise + */ + inline bool tryLock() { + return impl->tryLock(); + } + + /** + * unlocks the mutex + */ + inline void unlock() { + impl->unlock(); + } +}; + +/** + * A thread condition + * + * Thread conditions are used to let a different thread know that a certain + * condition might have changed. For instance, if you have a thread that + * waits until a counter exceeds a limit, the thread would look like this: + * + * <pre> + * class WaitCounter : public Arts::Thread + * { + * int counter; + * Arts::Mutex mutex; + * Arts::ThreadCondition cond; + * + * public: + * WaitCounter() : counter(0) {} + * + * void run() { // run will terminate once the counter reaches 20 + * mutex.lock(); + * while(counter < 20) + * cond.wait(mutex); + * mutex.unlock(); + * } + * + * void inc() { // inc will increment the counter and indicate the change + * mutex.lock(); + * counter++; + * cond.wakeOne(); + * mutex.unlock(); + * } + * }; + * </pre> + */ +class ARTS_EXPORT ThreadCondition { +private: + ThreadCondition_impl *impl; + +public: + ThreadCondition() + : impl(SystemThreads::the()->createThreadCondition_impl()) + { + } + + virtual ~ThreadCondition(); + + /** + * wakes one waiting thread + */ + inline void wakeOne() + { + impl->wakeOne(); + } + + /** + * wakes all waiting threads + */ + inline void wakeAll() + { + impl->wakeAll(); + } + + /** + * Waits until the condition changes. You will need to lock the mutex + * before calling this. Internally it will unlock the mutex (to let + * others change the condition), and relock it once the wait succeeds. + */ + inline void wait(Mutex& mutex) + { + impl->wait(mutex.impl); + } +}; + +class ARTS_EXPORT Semaphore { +private: + Semaphore_impl *impl; + +public: + Semaphore(int shared=0, int count=0) + { + impl = SystemThreads::the()->createSemaphore_impl(shared, count); + } + + virtual ~Semaphore(); + + inline void wait() + { + impl->wait(); + } + + inline int tryWait() + { + return impl->tryWait(); + } + + inline void post() + { + impl->post(); + } + + inline int getValue() + { + return impl->getValue(); + } +}; + +} + +#endif /* ARTS_MCOP_THREAD_H */ |