|
|
//*************************************************************************** /* * TOra - An Oracle Toolkit for DBA's and developers * Copyright (C) 2003 Quest Software, Inc * * 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; only version 2 of * the License is valid for this program. * * 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. * * As a special exception, you have permission to link this program * with the Oracle Client libraries and distribute executables, as long * as you follow the requirements of the GNU GPL in regard to all of the * software in the executable aside from Oracle client libraries. * * Specifically you are not permitted to link this program with the * Qt/UNIX, Qt/Windows or Qt Non Commercial products of TrollTech. * And you are not permitted to distribute binaries compiled against * these libraries without written consent from Quest Software, Inc. * Observe that this does not disallow linking to the Qt Free Edition. * * All trademarks belong to their respective owners. * ****************************************************************************/ #ifndef TOTHREAD_H #define TOTHREAD_H #include <qthread.h> /** This is an abstract class that defines something that is to be performed by a * thread. */ class toTask { public: virtual ~toTask() { } /** This member is called when the class is started. */ virtual void run(void) = 0; }; #ifndef QT_THREAD_SUPPORT #include <semaphore.h> class toSemaphore { private: sem_t Semaphore; void init(int val); toSemaphore(const toSemaphore &); public: toSemaphore(); toSemaphore(int val); ~toSemaphore(); void up(); void down(); int getValue(); }; #else /** Encapsulation of pthread semaphores. A semaphore can be raise to any value * but will wait till raised above zero when lowered below 0. Can also be implemented * without pthreads using Qt multithreaded primitives. Observe that these function * different than Qt semaphores. */ class toSemaphore { private: QMutex Mutex; QWaitCondition Condition; int Value; public: /** Create semaphore */ toSemaphore() : Condition() { Value=0; } /** Unimplemented copy constructor. */ toSemaphore(const toSemaphore &); /** Create semaphore * @param val Value of new semaphore. */ toSemaphore(int val) : Condition() { Value=val; } /** Increase semaphore value by 1. */ void up(); /** Decrease semaphore value by 1, wait for it to never go below 0. */ void down(); /** Get current semaphore value. */ int getValue(); }; #endif #include <list> #ifdef WIN32 class toLock { private: QMutex Mutex; public: toLock(void) : Mutex(false) { } toLock(const toLock &); void lock(void) { Mutex.lock(); } void unlock(void) { Mutex.unlock(); } }; class toThread { private: /** Not part of the API. */ class taskRunner : public QThread { public: toSemaphore StartSemaphore; toTask *Task; taskRunner(toTask *); virtual void run(void); friend class toThread; } Thread; static std::list<toThread *> *Threads; static toLock *Lock; static int LastID; static __declspec( thread ) int ThreadID; static int MainThread; toThread(const toThread &); public: toThread(toTask *); ~toThread(); void start(void); void startAsync(void); static void msleep(int msec); static bool mainThread(void); friend class taskRunner; }; #else #include <pthread.h> #include <signal.h> #include <time.h> /** A wrapper around the pthread mutexfunctions. A lock can only be locked * by one thread at a time and is the basis of most thread synchronisation. */ class toLock { private: /** Actual pthread mutex of class. */ pthread_mutex_t Mutex; toLock(const toLock &); public: /** Create lock */ toLock(void); ~toLock(); /** Lock this lock. */ void lock(void); /** Unlock this lock. */ void unlock(void); }; /** Used to create new threads of execution. When a thread exits it will delete the * thread and task objects so the calling thread must never delete a started thread. */ class toThread { private: static toThread *DeleteThread; static toLock *Lock; /** PThread identifier. */ pthread_t Thread; /** Thread attributes. */ pthread_attr_t ThreadAttr; /** Task to run in new thread. */ toTask *Task; /** Semaphore that is raised when new thread has started running. */ toSemaphore StartSemaphore; /** Initialise thread attributes. */ void initAttr(void); /** Called when thread is started to execute task. Pointer to @ref toThread * is passed as parameter. */ friend void *toThreadStartWrapper(void*); /** Main thread id */ static pthread_t MainThread; toThread(const toThread &); public: /** Create thread. * @param task Task to run. */ toThread(toTask *task); ~toThread(); /** Start thread and wait for other thread to start running. */ void start(void); /** Start thread and continue executing this thread until normal scheduling * handles over execution to child thread. */ void startAsync(void); /** Sleep in milliseconds. */ static void msleep(int msec); /** Returns true if this is the main thread. */ static bool mainThread(void); }; #endif /** This is a convenience class that holds a lock for the duration of the scope * of the object. It is very convenient to use if exceptions can be thrown, simply * declare an auto @ref toLocker to hold the lock. If any exception is thrown the * locker will be deallocated and the lock released. */ class toLocker { private: /** Lock held. */ toLock &Lock; toLocker(const toLocker &); public: /** Create locker. * @param lock Lock to hold. */ toLocker(toLock &lock) : Lock(lock) { Lock.lock(); } ~toLocker() { Lock.unlock(); } }; #endif