//***************************************************************************
/*
* TOra - An Oracle Toolkit for DBA's and developers
* Copyright (C) 2000-2001,2001 Underscore AB
*
* 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 Underscore AB. 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
/** 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;
};
#include
#ifdef WIN32
#include
class toSemaphore {
private:
QMutex Mutex;
QWaitCondition Condition;
int Value;
public:
toSemaphore()
: Condition()
{ Value=0; }
toSemaphore(const toSemaphore &);
toSemaphore(int val)
: Condition()
{ Value=val; }
void up();
void down();
int getValue();
};
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 *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
#include
#include
#include
/** 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:
/** Actual semaphore.
*/
sem_t Semaphore;
/** Initialise semaphore.
* @param val Value to init semaphore to.
*/
void init(int val);
toSemaphore(const toSemaphore &);
public:
/** Create semaphore
*/
toSemaphore();
/** Create semaphore
* @param val Value of new semaphore.
*/
toSemaphore(int val);
~toSemaphore();
/** 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();
};
/** 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