Qt-UI

Job Queue

Mandelbrot Example | | Threaded Image Conversion

In the following we will outline another threading pattern: a job queue.

A job queue executes jobs one after another. There is not one thread for each job but one worker thread that works off all jobs.

First let’s define a base class for a job. It is derived from std::string to encode information about the job, e.g. a command line or file to work on. It also has a pure virtual execute() method that does the job:

class Job: public std::string
{
   public:

   Job() : std::string() {}
   Job(const std::string &s) : std::string(s) {}
   virtual ~Job() {}

   virtual int execute() = 0;
};

Now we define a job queue:

typedef std::vector<Job *> Jobs;

And now we define a worker class that maintains the job queue:

class worker : public QThread
{
   Q_OBJECT;

   public:

   //! default constructor
   worker(QObject *parent=0)
      : QThread(parent)
   {
      failure=0;
   }

   //! destructor
   virtual ~worker()
      {abort_jobs();}

   void run_job(Job *job)
   {
      block_jobs();
      jobs.push_back(job);
      unblock_jobs();
      start_jobs();
   }

   int finish_jobs()
   {
      wait4jobs();
      return(failure);
   }

   protected:

   virtual void block_jobs() {mutex.lock();}
   virtual void unblock_jobs() {mutex.unlock();}

   virtual void start_jobs()
   {
      if (!isRunning())
         start(LowPriority); // calls run() in a new thread
   }

   virtual void wait4jobs() {wait();}

   virtual void run()
   {
      int errorcode;

      block_jobs();

      failure=0;

      while (!jobs.empty())
      {
         Job *job=jobs[0];

         unblock_jobs();

         errorcode=job->execute();

         if (!errorcode)
            emit finishedJob(*job);
         else
         {
            emit failedJob(*job, errorcode);
            failure++;
         }

         block_jobs();

         jobs.erase(jobs.begin());
      }

      unblock_jobs();
   }

   private:

   Jobs jobs;
   int failure;

   QMutex mutex;

   signals:

   void finishedJob(const std::string &job);
   void failedJob(const std::string &job, int errorcode);
};


Mandelbrot Example | | Threaded Image Conversion

Options: