summaryrefslogtreecommitdiffstats
path: root/mcop/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'mcop/thread.h')
-rw-r--r--mcop/thread.h375
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 */