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
}