PCMThread.cpp

Go to the documentation of this file.
00001 
00002 //
00003 // This source file is a part of ParCompMark
00004 // Parallel Compositing Benchmark Framework
00005 //
00006 // for latest info see http://parcompmark.sourceforge.net
00007 
00008 //
00009 // Copyright (C) 2006 IT2 ParCompMark Dev. Team
00010 // 
00011 // This program is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2
00014 // of the License, or (at your option) any later version.
00015 // 
00016 // This program is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 // GNU General Public License for more details.
00020 // 
00021 // You should have received a copy of the GNU General Public License
00022 // along with this program; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00024 
00025 //
00026 // Inner includes
00027 //
00028 
00029 #include "../include/PCMThread.h"
00030 
00031 namespace ParCompMark
00032 {
00033 
00034   //
00035   // Constructors & destructor
00036   //
00037 
00038   Thread::Thread(const std::string & name)
00039         // You have to initialize the following attributes:
00040         // - mThreadName
00041         // - mWait
00042         // - mStopRequested
00043         // - mJoinable
00044         // - mWaitThread
00045         // - mThread
00046         // - mCondition
00047         // - mConditionMutex
00048         // - mRunning
00049         // - mCurrentFPS
00050         // - mExpectedFPS
00051         // - mIterationNumber
00052   {
00053         mThreadName = name;
00054         mWait = new bool;
00055         *mWait.getPtr() = false;
00056         mStopRequested = false;
00057         mRunning = false;
00058         mThread = 0;
00059         mJoinable = false;
00060 
00061         if(0 != pthread_cond_init(&mCondition, 0))
00062         {
00063          Except(INTERNAL_ERROR, "Thread::wait()", "Unable to init condition variable.");
00064         }
00065         if(0 != pthread_mutex_init(&mConditionMutex, 0))
00066         {
00067          Except(INTERNAL_ERROR, "Thread::wait()", "Unable to init mutex variable.");
00068         }
00069 
00070         mCurrentFPS = 0;
00071         mExpectedFPS = 0;
00072         mIterationNumber = 0;
00073   }
00074 
00075  /*----------------------------------------------------------------------*/
00076 
00077   Thread::~Thread()
00078   {
00079         pthread_mutex_destroy(&mConditionMutex);
00080         pthread_cond_destroy(&mCondition);
00081 
00082         if(mRunning)
00083          shutDownThread();
00084 
00085         Logger::getInstance()->log(Logger::DEBUG, "Thread " + mThreadName + " is dying.");
00086 
00087   }
00088 
00089  /*----------------------------------------------------------------------*/
00090 
00091   //
00092   // Class methods
00093   //
00094 
00095   void *Thread::entryPoint(void *arg)
00096   {
00097 
00098         Thread *pthis = (Thread *) arg;
00099 
00100         // Setting cancellation state
00101         if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
00102         {
00103          Except(INTERNAL_ERROR, "Thread::entryPoint", "Unable to set cancel enabling");
00104         }
00105         // Setting cancellation type
00106         if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))
00107         {
00108          Except(INTERNAL_ERROR, "Thread::entryPoint", "Unable to set cancelling type");
00109         }
00110 
00111         pthis->thread();
00112 
00113         pthis->mRunning = false;
00114         Logger::getInstance()->log(Logger::DEBUG, "Thread " + pthis->mThreadName + " finished.");
00115 
00116         // Proper termination
00117         pthread_exit(0);
00118   }
00119 
00120  /*----------------------------------------------------------------------*/
00121 
00122   //
00123   // Methods
00124   //
00125 
00126   void Thread::initThread(const u32 & iterationNumber, const u32 & expectedFPS,
00127                          const bool & joinable, const bool & waitThread)
00128   {
00129         Assert(joinable || !waitThread, INVALID_OPERATION_ERROR, "Thread::initThread");
00130         Assert(!((waitThread) && iterationNumber == 0), INVALID_OPERATION_ERROR, "Thread::initThread");
00131 
00132         mExpectedFPS = expectedFPS;
00133         mIterationNumber = iterationNumber;
00134         mJoinable = joinable;
00135         mWaitThread = waitThread;
00136   }
00137 
00138  /*----------------------------------------------------------------------*/
00139 
00140   void Thread::threadInitialize()
00141   {
00142   }
00143 
00144  /*----------------------------------------------------------------------*/
00145 
00146   void Thread::threadFinalize()
00147   {
00148   }
00149 
00150  /*----------------------------------------------------------------------*/
00151 
00152   void Thread::startThread()
00153   {
00154 
00155         // The thread can not run
00156         Assert(!mRunning, INVALID_OPERATION_ERROR, "Thread::startThread");
00157 
00158         pthread_attr_t attr;
00159 
00160         // Set detached state
00161         pthread_attr_init(&attr);
00162 
00163         if(mJoinable)
00164         {
00165          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00166         } else
00167         {
00168          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00169         }
00170 
00171         // Start new thread
00172         mRunning = true;
00173         pthread_create(&mThread, &attr, &(Thread::entryPoint), (void *) this);
00174 
00175         pthread_attr_destroy(&attr);
00176         Logger::getInstance()->log(Logger::DEBUG, "Thread " + mThreadName + " started.");
00177   }
00178 
00179  /*----------------------------------------------------------------------*/
00180 
00181   void Thread::joinThread()
00182   {
00183         //TODO: assert!
00184         //Assert(!(mIterationNumber == 0 && !mStopRequested && mRunning), INVALID_OPERATION_ERROR,
00185 
00186         // "Thread::joinThread()");
00187         Assert(mJoinable, INVALID_OPERATION_ERROR, "Thread::joinThread()");
00188 
00189         if(!mRunning)
00190         {
00191          return;
00192         }
00193 
00194         if(pthread_join(mThread, 0))
00195         {
00196          Except(INTERNAL_ERROR, "Thread::joinThread()", "Unable to join thread " + mThreadName);
00197         }
00198 
00199   }
00200 
00201  /*----------------------------------------------------------------------*/
00202 
00203   void Thread::shutDownThread()
00204   {
00205         // The thread must run
00206         Assert(mRunning, INVALID_OPERATION_ERROR, "Thread::shutDownThread()");
00207         Assert(mThread, NULL_POINTER_ERROR, "Thread::shutDownThread()");
00208         Logger::getInstance()->log(Logger::DEBUG, "Thread " + mThreadName + " is going down.");
00209 
00210         // Wait for thread termination
00211 
00212         if(mWaitThread)
00213         {
00214          if(pthread_join(mThread, 0))
00215          {
00216                 Except(INTERNAL_ERROR, "Thread::shutDownThread()", "Unable join thread " + mThreadName);
00217          }
00218         } else
00219         {
00220          if(pthread_cancel(mThread))
00221          {
00222                 Except(INTERNAL_ERROR, "Thread::shutDownThread()", "Unable to shut down thread " + mThreadName);
00223          }
00224         }
00225 
00226         mStopRequested = false;
00227         mRunning = false;
00228         mThread = 0;
00229         Logger::getInstance()->log(Logger::DEBUG, "Thread " + mThreadName + " is down.");
00230   }
00231 
00232  /*----------------------------------------------------------------------*/
00233 
00234   void Thread::stopThread()
00235   {
00236         Logger::getInstance()->log(Logger::DEBUG, "Stopping " + mThreadName);
00237         mStopRequested = true;
00238   }
00239 
00240  /*----------------------------------------------------------------------*/
00241 
00242   void Thread::go()
00243   {
00244 
00245         if(pthread_mutex_lock(&mConditionMutex) != 0)
00246         {
00247          Except(INTERNAL_ERROR, "Thread::go", "??? can't lock");
00248         }
00249 
00250         if(pthread_cond_signal(&mCondition) != 0)
00251         {
00252          Except(INTERNAL_ERROR, "Thread::go", "??? can't go");
00253         }
00254 
00255         if(pthread_mutex_unlock(&mConditionMutex) != 0)
00256         {
00257          Except(INTERNAL_ERROR, "Thread::go", "??? can't unlock");
00258         }
00259 
00260   }
00261 
00262  /*----------------------------------------------------------------------*/
00263 
00264   void Thread::thread()
00265   {
00266         threadInitialize();
00267 
00268         yield();
00269 
00270         if(mIterationNumber == 0)
00271          // Infinite loop
00272          for(;;)
00273          {
00274 
00275                 if(iteration())
00276                  break;
00277          }
00278 
00279         else
00280          // Specified number of loops
00281          for(u32 i = 0; i < mIterationNumber; i++)
00282          {
00283                 if(iteration())
00284                  break;
00285          }
00286 
00287         threadFinalize();
00288 
00289         yield();
00290 
00291   }
00292 
00293  /*----------------------------------------------------------------------*/
00294 
00295   void Thread::task()
00296   {
00297 
00298         // Nothing to do, but do something :)
00299         Timer::sleep(0.01);
00300 
00301   }
00302 
00303  /*----------------------------------------------------------------------*/
00304 
00305   void Thread::wait()
00306   {
00307 
00308         if(pthread_mutex_lock(&mConditionMutex) != 0)
00309         {
00310          Except(INTERNAL_ERROR, "Thread::wait", "??? can't lock");
00311         }
00312 
00313         if(pthread_cond_wait(&mCondition, &mConditionMutex) != 0)
00314         {
00315          Except(INTERNAL_ERROR, "Thread::wait", "??? can't cond_wait");
00316         }
00317 
00318         if(pthread_mutex_unlock(&mConditionMutex) != 0)
00319         {
00320          Except(INTERNAL_ERROR, "Thread::wait", "??? can't unlock");
00321         }
00322 
00323   }
00324 
00325  /*----------------------------------------------------------------------*/
00326 
00327 }