Source Code (Use browser search to find items of interest.)
Class Index
katalog'KThread (./kdegraphics/katalog/kthread.h:16)
class KThread : QObject
{
Q_OBJECT
friend KThreadWorker;
KThreadWorker *mWorker;
KThread_data_ *d;
bool mRunning;
bool mOk;
bool mFinished;
bool mCanceled;
public:
/**
* Returns true if actual threads are supported
*
* Without thread support this class will behave
* according to spec but realtime behaviour will be
* sub-optimal.
**/
static bool supported();
KThread(KThreadWorker *);
~KThread();
/**
* Activate the thread
*/
void start();
/**
* Stop the thread at the first syncpoint.
*
* When the thread is actually canceled
* the 'canceled' signal is emitted
*
* If 'wait' is true, this function
* does not return before the thread is
* either canceled or finished.
*/
void cancel(bool wait=false);
/**
* Wait for 'msec' milliseconds for
* the thread to finish.
*
* This function returns 'true' if
* the thread has finished or 'false'
* when 'msec' miliseconds have passed.
*
* NOTE1: This function can also be used to
* wait for a thread which has been canceled.
*/
bool finish(int msec);
/**
* Returns 'true' when thread exited normally
*/
bool isFinished() { return mFinished; }
/**
* Returns 'true' when thread was canceled
*/
bool isCanceled() { return mCanceled; }
/**
* Returns 'true' when activation of thread was succesfull
*/
bool isOk() { return mOk; }
signals:
void progress(int);
void finished();
void canceled();
protected slots:
// For internal use only.
void slotAttention(int);
protected:
// For internal use only.
void notifyMainThread(char command, bool wait=true);
};
katalog'KThread::KThread() (./kdegraphics/katalog/kthread.cpp:66)
KThread::KThread(KThreadWorker *worker)
: mWorker(worker), mRunning(false),
mOk(false), mFinished(false), mCanceled(false)
{
d = new KThread_data_();
if (worker->d) return; // Already in use!
worker->d = d;
d->thread = this;
d->sync = false;
d->canceled = false;
#ifndef KTR_NO_THREADS
// Creating pipe for worker -> main-thread signalisation
d->fd[0] = d->fd[1] = -1;
int result;
result = pipe(d->fd);
if (result < 0)
{
fprintf(stderr, "KThread pipe(): %s\n", strerror(errno));
return;
}
long fdOptions;
fdOptions = fcntl(d->fd[0], F_GETFL);
if (fdOptions < 0)
{
fprintf(stderr, "KThread fcntl(F_GETFL): %s\n", strerror(errno));
return;
}
result = fcntl(d->fd[0], F_SETFL, fdOptions | O_NONBLOCK);
if (result < 0)
{
fprintf(stderr, "KThread fcntl(F_SETFL): %s\n", strerror(errno));
return;
}
d->notifier = new QSocketNotifier(d->fd[0], QSocketNotifier::Read);
d->notifier->setEnabled(true);
connect(d->notifier, SIGNAL(activated(int)),
this, SLOT(slotAttention(int)));
#endif
#ifdef KTR_PTHREADS
pthread_mutex_init(&(d->mutex), 0);
pthread_cond_init(&(d->cond), 0);
#endif
}
katalog'KThread::~KThread() (./kdegraphics/katalog/kthread.cpp:114)
KThread::~KThread()
{
#ifndef KTR_NO_THREADS
int result;
delete d->notifier;
d->notifier = 0;
if (d->fd[0] != -1)
{
result = close(d->fd[0]);
if (result < 0)
{
fprintf(stderr, "KThread close(d->fd[0]): %s\n", strerror(errno));
return;
}
d->fd[0] = -1;
}
if (d->fd[1] != -1)
{
result = close(d->fd[1]);
if (result < 0)
{
fprintf(stderr, "KThread close(d->fd[1]): %s\n", strerror(errno));
return;
}
d->fd[1] = -1;
}
#endif
#ifdef KTR_PTHREADS
pthread_mutex_destroy( &(d->mutex) );
#endif
delete d;
}
bool
katalog'KThread::supported() (./kdegraphics/katalog/kthread.cpp:150)
KThread::supported()
{
#ifdef KTR_NO_THREADS
return false;
#else
return true;
#endif
}
void
katalog'KThread::start() (./kdegraphics/katalog/kthread.cpp:160)
KThread::start()
{
kapp->processEvents();
kapp->syncX();
if (mRunning) return;
#ifdef KTR_NO_THREADS
mWorker->launch();
#endif
#ifdef KTR_PTHREADS
int result = pthread_create(&(d->pthread), 0, launch_thread, (void *) mWorker);
if (result < 0)
{
fprintf(stderr, "KThread pthread_exec(): %s\n", strerror(errno));
return;
}
#endif
}
void
katalog'KThread::cancel() (./kdegraphics/katalog/kthread.cpp:179)
KThread::cancel(bool wait)
{
d->canceled = true;
// The following assignment must come last
d->sync = true;
if (wait) finish(0);
}
bool
katalog'KThread::finish() (./kdegraphics/katalog/kthread.cpp:188)
KThread::finish(int msec)
{
if (mFinished || mCanceled)
return true;
#ifdef KTR_NO_THREADS
(void) msec; // Silence compiler
#else
QTime startTime = QTime::currentTime();
do {
int result;
fd_set fdSet;
fd_set nullSet;
FD_ZERO(&fdSet);
FD_ZERO(&nullSet);
FD_SET(d->fd[0], &fdSet);
// Wait for waitTime
if (msec)
{
int timeWaited = startTime.msecsTo(QTime::currentTime());
if (timeWaited < 0)
break;
int waitTime = msec-timeWaited;
if (waitTime < 0)
break;
struct timeval time_s;
time_s.tv_sec = waitTime / 1000;
time_s.tv_usec = 1000*(waitTime-time_s.tv_sec*1000);
result = select( d->fd[0]+1, &fdSet, &nullSet, &nullSet, &time_s);
}
else
{
result = select( d->fd[0]+1, &fdSet, &nullSet, &nullSet, 0);
}
if (result >0)
{
slotAttention(d->fd[0]);
if( mFinished || mCanceled)
return true;
}
}
while (true);
#endif
return false;
}
//
// This function gets called whenever the worker-thread has something
// to tell to the main-thread.
//
void
katalog'KThread::slotAttention() (./kdegraphics/katalog/kthread.cpp:247)
KThread::slotAttention(int)
{
char command;
#ifdef KTR_NO_THREADS
command = d->command;
#else
int result;
// Read command from pipe
result = ::read(d->fd[0], &command, sizeof(command));
if (result < 0)
{
fprintf(stderr, "KThread read(d->fd[0]): %s\n", strerror(errno));
return;
}
#endif
#ifdef KTR_PTHREADS
result = pthread_mutex_lock(&(d->mutex));
if (result < 0)
{
fprintf(stderr, "KThread pthread_lock_mutex(): %s\n", strerror(errno));
}
#endif
// Handle command
switch (command)
{
case KTR_PROGRESS:
fprintf(stderr, "Emitting progress %d\n", d->progress);
emit progress(d->progress);
break;
case KTR_FINISHED:
#ifdef KTR_PTHREADS
pthread_join(d->pthread, 0);
#endif
fprintf(stderr, "Thread has finished\n");
emit finished();
mFinished = true;
break;
case KTR_CANCELED:
#ifdef KTR_PTHREADS
pthread_join(d->pthread, 0);
#endif
fprintf(stderr, "Thread is canceled\n");
emit canceled();
mCanceled = true;
break;
default:
fprintf(stderr, "KThread: received unknown command from thread.\n");
break;
}
// Let worker thread continue
#ifdef KTR_PTHREADS
result = pthread_cond_signal(&(d->cond));
if (result < 0)
{
fprintf(stderr, "KThread pthread_cond_signal(): %s\n", strerror(errno));
}
result = pthread_mutex_unlock(&(d->mutex));
if (result < 0)
{
fprintf(stderr, "KThread pthread_unlock_mutex(): %s\n", strerror(errno));
}
#endif
}
void
katalog'KThread::notifyMainThread() (./kdegraphics/katalog/kthread.cpp:316)
KThread::notifyMainThread(char command, bool wait)
{
#ifdef KTR_NO_THREADS
d->command = command;
slotAttention(0);
#else
int result;
// Lock mutex
#ifdef KTR_PTHREADS
result = pthread_mutex_lock(&(d->mutex));
if (result < 0)
{
fprintf(stderr, "KThreadWorker pthread_lock_mutex(): %s\n", strerror(errno));
}
#endif // KTR_PTHREADS
// Signal main-thread
::write( d->fd[1], &command, sizeof(command));
// Wait for response
#ifdef KTR_PTHREADS
if (wait)
{
result = pthread_cond_wait(&(d->cond), &(d->mutex));
if (result < 0)
{
fprintf(stderr, "KThreadWorker pthread_cond_wait(): %s\n", strerror(errno));
}
}
result = pthread_mutex_unlock(&(d->mutex));
if (result < 0)
{
fprintf(stderr, "KThreadWorker pthread_unlock_mutex(): %s\n", strerror(errno));
}
#endif // KTR_PTHREADS
#endif // KTR_NO_TRHEADS
}